From 9b2a79faf15a99bb5f1a8f224a7bd8de18a190ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Thu, 28 Dec 2023 01:29:06 +0200 Subject: [PATCH] Adjust the import/export code to have the game state passed --- src/openrct2-ui/scripting/ScTitleSequence.hpp | 6 +- src/openrct2-ui/title/TitleSequencePlayer.cpp | 9 +- src/openrct2-ui/windows/LoadSave.cpp | 10 +- src/openrct2/Context.cpp | 6 +- src/openrct2/Editor.cpp | 5 +- src/openrct2/Game.cpp | 11 +- src/openrct2/ParkImporter.h | 5 +- src/openrct2/ReplayManager.cpp | 7 +- src/openrct2/command_line/ConvertCommand.cpp | 11 +- src/openrct2/network/NetworkBase.cpp | 9 +- src/openrct2/park/ParkFile.cpp | 119 +++++++++--------- src/openrct2/park/ParkFile.h | 6 +- src/openrct2/rct1/S4Importer.cpp | 8 +- src/openrct2/rct2/S6Importer.cpp | 4 +- src/openrct2/scenario/Scenario.h | 7 +- test/tests/PlayTests.cpp | 5 +- test/tests/S6ImportExportTests.cpp | 14 ++- 17 files changed, 154 insertions(+), 88 deletions(-) diff --git a/src/openrct2-ui/scripting/ScTitleSequence.hpp b/src/openrct2-ui/scripting/ScTitleSequence.hpp index 96216558f7..7fcd63e596 100644 --- a/src/openrct2-ui/scripting/ScTitleSequence.hpp +++ b/src/openrct2-ui/scripting/ScTitleSequence.hpp @@ -14,6 +14,7 @@ # include # include # include +# include # include # include # include @@ -253,7 +254,10 @@ namespace OpenRCT2::Scripting auto parkImporter = ParkImporter::Create(handle->HintPath); auto result = parkImporter->LoadFromStream(handle->Stream.get(), isScenario); objectMgr.LoadObjects(result.RequiredObjects); - parkImporter->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + parkImporter->Import(gameState); auto old = gLoadKeepWindowsOpen; diff --git a/src/openrct2-ui/title/TitleSequencePlayer.cpp b/src/openrct2-ui/title/TitleSequencePlayer.cpp index 0642a5dbb3..55276722cb 100644 --- a/src/openrct2-ui/title/TitleSequencePlayer.cpp +++ b/src/openrct2-ui/title/TitleSequencePlayer.cpp @@ -304,7 +304,9 @@ namespace OpenRCT2::Title auto& objectManager = GetContext()->GetObjectManager(); objectManager.LoadObjects(result.RequiredObjects); - parkImporter->Import(); + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + parkImporter->Import(gameState); MapAnimationAutoCreate(); } PrepareParkForPlayback(); @@ -343,7 +345,10 @@ namespace OpenRCT2::Title auto& objectManager = GetContext()->GetObjectManager(); objectManager.LoadObjects(result.RequiredObjects); - parkImporter->Import(); + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + + parkImporter->Import(gameState); } PrepareParkForPlayback(); success = true; diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 150ae0d253..731493737f 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -39,6 +39,8 @@ #include #include +using namespace OpenRCT2; + #pragma region Widgets static constexpr StringId WINDOW_TITLE = STR_NONE; @@ -264,6 +266,8 @@ static void Select(const char* path) char pathBuffer[MAX_PATH]; SafeStrCpy(pathBuffer, path, sizeof(pathBuffer)); + auto& gameState = GetGameState(); + switch (_type & 0x0F) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME): @@ -284,7 +288,7 @@ static void Select(const char* path) case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME): SetAndSaveConfigPath(gConfigGeneral.LastSaveGameDirectory, pathBuffer); - if (ScenarioSave(pathBuffer, gConfigGeneral.SavePluginData ? 1 : 0)) + if (ScenarioSave(gameState, pathBuffer, gConfigGeneral.SavePluginData ? 1 : 0)) { gScenarioSavePath = pathBuffer; gCurrentLoadedPath = pathBuffer; @@ -322,7 +326,7 @@ static void Select(const char* path) case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE): SetAndSaveConfigPath(gConfigGeneral.LastSaveLandscapeDirectory, pathBuffer); gScenarioFileName = std::string(String::ToStringView(pathBuffer, std::size(pathBuffer))); - if (ScenarioSave(pathBuffer, gConfigGeneral.SavePluginData ? 3 : 2)) + if (ScenarioSave(gameState, pathBuffer, gConfigGeneral.SavePluginData ? 3 : 2)) { gCurrentLoadedPath = pathBuffer; WindowCloseByClass(WindowClass::Loadsave); @@ -343,7 +347,7 @@ static void Select(const char* path) gParkFlags &= ~PARK_FLAGS_SPRITES_INITIALISED; gEditorStep = EditorStep::Invalid; gScenarioFileName = std::string(String::ToStringView(pathBuffer, std::size(pathBuffer))); - int32_t success = ScenarioSave(pathBuffer, gConfigGeneral.SavePluginData ? 3 : 2); + int32_t success = ScenarioSave(gameState, pathBuffer, gConfigGeneral.SavePluginData ? 3 : 2); gParkFlags = parkFlagsBackup; if (success) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index d7a9281982..e8e21ea74e 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -647,7 +647,11 @@ namespace OpenRCT2 GameUnloadScripts(); _objectManager->LoadObjects(result.RequiredObjects); - parkImporter->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = ::GetGameState(); + parkImporter->Import(gameState); + gScenarioSavePath = path; gCurrentLoadedPath = path; gFirstTimeSaving = true; diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index 3dda00d830..455b8316fd 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -282,7 +282,10 @@ namespace Editor auto importer = ParkImporter::CreateParkFile(context->GetObjectRepository()); auto loadResult = importer->Load(path); objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); AfterLoadCleanup(true); return true; diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 118aee7062..4fa3378d3f 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -13,6 +13,7 @@ #include "Context.h" #include "Editor.h" #include "FileClassifier.h" +#include "GameState.h" #include "GameStateSnapshots.h" #include "Input.h" #include "OpenRCT2.h" @@ -74,6 +75,8 @@ #include #include +using namespace OpenRCT2; + uint16_t gCurrentDeltaTime; uint8_t gGamePaused = 0; int32_t gGameSpeed = 1; @@ -638,7 +641,9 @@ void SaveGameCmd(u8string_view name /* = {} */) void SaveGameWithName(u8string_view name) { LOG_VERBOSE("Saving to %s", u8string(name).c_str()); - if (ScenarioSave(name, gConfigGeneral.SavePluginData ? 1 : 0)) + + auto& gameState = GetGameState(); + if (ScenarioSave(gameState, name, gConfigGeneral.SavePluginData ? 1 : 0)) { LOG_VERBOSE("Saved to %s", u8string(name).c_str()); gCurrentLoadedPath = name; @@ -760,7 +765,9 @@ void GameAutosave() File::Copy(path, backupPath, true); } - if (!ScenarioSave(path, saveFlags)) + auto& gameState = GetGameState(); + + if (!ScenarioSave(gameState, path, saveFlags)) Console::Error::WriteLine("Could not autosave the scenario. Is the save folder writeable?"); } diff --git a/src/openrct2/ParkImporter.h b/src/openrct2/ParkImporter.h index e6bfc9b3ba..7fd903872e 100644 --- a/src/openrct2/ParkImporter.h +++ b/src/openrct2/ParkImporter.h @@ -24,7 +24,8 @@ struct IObjectRepository; namespace OpenRCT2 { struct IStream; -} + struct GameState_t; +} // namespace OpenRCT2 struct ScenarioIndexEntry; @@ -56,7 +57,7 @@ public: virtual ParkLoadResult LoadFromStream( OpenRCT2::IStream* stream, bool isScenario, bool skipObjectCheck = false, const u8string& path = {}) abstract; - virtual void Import() abstract; + virtual void Import(OpenRCT2::GameState_t& gameState) abstract; virtual bool GetDetails(ScenarioIndexEntry* dst) abstract; }; diff --git a/src/openrct2/ReplayManager.cpp b/src/openrct2/ReplayManager.cpp index 9fbb9c0e8e..8d92fcbd42 100644 --- a/src/openrct2/ReplayManager.cpp +++ b/src/openrct2/ReplayManager.cpp @@ -252,9 +252,10 @@ namespace OpenRCT2 auto& objManager = context->GetObjectManager(); auto objects = objManager.GetPackableObjects(); + auto& gameState = GetGameState(); auto exporter = std::make_unique(); exporter->ExportObjectsList = objects; - exporter->Export(replayData->parkData); + exporter->Export(gameState, replayData->parkData); replayData->timeRecorded = std::chrono::seconds(std::time(nullptr)).count(); @@ -535,7 +536,9 @@ namespace OpenRCT2 auto loadResult = importer->LoadFromStream(&data.parkData, false); objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); EntityTweener::Get().Reset(); diff --git a/src/openrct2/command_line/ConvertCommand.cpp b/src/openrct2/command_line/ConvertCommand.cpp index ab9db86285..d96878e244 100644 --- a/src/openrct2/command_line/ConvertCommand.cpp +++ b/src/openrct2/command_line/ConvertCommand.cpp @@ -9,6 +9,7 @@ #include "../Context.h" #include "../FileClassifier.h" +#include "../GameState.h" #include "../OpenRCT2.h" #include "../ParkImporter.h" #include "../common.h" @@ -22,6 +23,8 @@ #include +using namespace OpenRCT2; + static void WriteConvertFromAndToMessage(FileExtension sourceFileType, FileExtension destinationFileType); static u8string GetFileTypeFriendlyName(FileExtension fileType); @@ -98,7 +101,9 @@ exitcode_t CommandLine::HandleCommandConvert(CommandLineArgEnumerator* enumerato objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); } catch (const std::exception& ex) { @@ -120,7 +125,9 @@ exitcode_t CommandLine::HandleCommandConvert(CommandLineArgEnumerator* enumerato // correct initial view WindowCloseByClass(WindowClass::MainWindow); - exporter->Export(destinationPath); + auto& gameState = GetGameState(); + + exporter->Export(gameState, destinationPath); } catch (const std::exception& ex) { diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 0d4c4ead6c..cd9725dadd 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -2797,7 +2797,10 @@ bool NetworkBase::LoadMap(IStream* stream) auto importer = ParkImporter::CreateParkFile(context.GetObjectRepository()); auto loadResult = importer->LoadFromStream(stream, false); objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); EntityTweener::Get().Reset(); MapAnimationAutoCreate(); @@ -2820,7 +2823,9 @@ bool NetworkBase::SaveMap(IStream* stream, const std::vector(); exporter->ExportObjectsList = objects; - exporter->Export(*stream); + + auto& gameState = GetGameState(); + exporter->Export(gameState, *stream); result = true; } catch (const std::exception& e) diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 508e23f330..692145313f 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -143,23 +143,23 @@ namespace OpenRCT2 ReadWritePackedObjectsChunk(*_os); } - void Import() + void Import(GameState_t& gameState) { auto& os = *_os; - ReadWriteTilesChunk(os); - ReadWriteBannersChunk(os); - ReadWriteRidesChunk(os); - ReadWriteEntitiesChunk(os); - ReadWriteScenarioChunk(os); - ReadWriteGeneralChunk(os); - ReadWriteParkChunk(os); - ReadWriteClimateChunk(os); - ReadWriteResearchChunk(os); - ReadWriteNotificationsChunk(os); - ReadWriteInterfaceChunk(os); - ReadWriteCheatsChunk(os); - ReadWriteRestrictedObjectsChunk(os); - ReadWritePluginStorageChunk(os); + ReadWriteTilesChunk(gameState, os); + ReadWriteBannersChunk(gameState, os); + ReadWriteRidesChunk(gameState, os); + ReadWriteEntitiesChunk(gameState, os); + ReadWriteScenarioChunk(gameState, os); + ReadWriteGeneralChunk(gameState, os); + ReadWriteParkChunk(gameState, os); + ReadWriteClimateChunk(gameState, os); + ReadWriteResearchChunk(gameState, os); + ReadWriteNotificationsChunk(gameState, os); + ReadWriteInterfaceChunk(gameState, os); + ReadWriteCheatsChunk(gameState, os); + ReadWriteRestrictedObjectsChunk(gameState, os); + ReadWritePluginStorageChunk(gameState, os); if (os.GetHeader().TargetVersion < 0x4) { UpdateTrackElementsRideType(); @@ -169,7 +169,7 @@ namespace OpenRCT2 gInitialCash = gCash; } - void Save(IStream& stream) + void Save(GameState_t& gameState, IStream& stream) { OrcaStream os(stream, OrcaStream::Mode::WRITING); @@ -180,27 +180,27 @@ namespace OpenRCT2 ReadWriteAuthoringChunk(os); ReadWriteObjectsChunk(os); - ReadWriteTilesChunk(os); - ReadWriteBannersChunk(os); - ReadWriteRidesChunk(os); - ReadWriteEntitiesChunk(os); - ReadWriteScenarioChunk(os); - ReadWriteGeneralChunk(os); - ReadWriteParkChunk(os); - ReadWriteClimateChunk(os); - ReadWriteResearchChunk(os); - ReadWriteNotificationsChunk(os); - ReadWriteInterfaceChunk(os); - ReadWriteCheatsChunk(os); - ReadWriteRestrictedObjectsChunk(os); - ReadWritePluginStorageChunk(os); + ReadWriteTilesChunk(gameState, os); + ReadWriteBannersChunk(gameState, os); + ReadWriteRidesChunk(gameState, os); + ReadWriteEntitiesChunk(gameState, os); + ReadWriteScenarioChunk(gameState, os); + ReadWriteGeneralChunk(gameState, os); + ReadWriteParkChunk(gameState, os); + ReadWriteClimateChunk(gameState, os); + ReadWriteResearchChunk(gameState, os); + ReadWriteNotificationsChunk(gameState, os); + ReadWriteInterfaceChunk(gameState, os); + ReadWriteCheatsChunk(gameState, os); + ReadWriteRestrictedObjectsChunk(gameState, os); + ReadWritePluginStorageChunk(gameState, os); ReadWritePackedObjectsChunk(os); } - void Save(const std::string_view path) + void Save(GameState_t& gameState, const std::string_view path) { FileStream fs(path, FILE_MODE_WRITE); - Save(fs); + Save(gameState, fs); } ScenarioIndexEntry ReadScenarioChunk() @@ -415,12 +415,13 @@ namespace OpenRCT2 } } - void ReadWriteScenarioChunk(OrcaStream& os) + void ReadWriteScenarioChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::SCENARIO, [&os](OrcaStream::ChunkStream& cs) { cs.ReadWrite(gScenarioCategory); ReadWriteStringTable(cs, gScenarioName, "en-GB"); + // TODO: Use the passed gameState instead of the global one. auto& park = GetContext()->GetGameState()->GetPark(); ReadWriteStringTable(cs, park.Name, "en-GB"); @@ -464,10 +465,10 @@ namespace OpenRCT2 }); } - void ReadWriteGeneralChunk(OrcaStream& os) + void ReadWriteGeneralChunk(GameState_t& gameState, OrcaStream& os) { const auto version = os.GetHeader().TargetVersion; - auto found = os.ReadWriteChunk(ParkFileChunkType::GENERAL, [this, &os, &version](OrcaStream::ChunkStream& cs) { + auto found = os.ReadWriteChunk(ParkFileChunkType::GENERAL, [&](OrcaStream::ChunkStream& cs) { // Only GAME_PAUSED_NORMAL from gGamePaused is relevant. if (cs.GetMode() == OrcaStream::Mode::READING) { @@ -480,13 +481,14 @@ namespace OpenRCT2 const uint8_t isPaused = (gGamePaused & GAME_PAUSED_NORMAL); cs.Write(isPaused); } - cs.ReadWrite(GetGameState().CurrentTicks); + cs.ReadWrite(gameState.CurrentTicks); if (cs.GetMode() == OrcaStream::Mode::READING) { uint16_t monthTicks; uint32_t monthsElapsed; cs.ReadWrite(monthTicks); cs.ReadWrite(monthsElapsed); + // TODO: Use the passed gameState instead of the global one. GetContext()->GetGameState()->SetDate(Date(monthsElapsed, monthTicks)); } else @@ -600,7 +602,7 @@ namespace OpenRCT2 cs.ReadWrite(calcData.StationFlags); } - void ReadWriteInterfaceChunk(OrcaStream& os) + void ReadWriteInterfaceChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::INTERFACE, [](OrcaStream::ChunkStream& cs) { cs.ReadWrite(gSavedView.x); @@ -620,7 +622,7 @@ namespace OpenRCT2 }); } - void ReadWriteCheatsChunk(OrcaStream& os) + void ReadWriteCheatsChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::CHEATS, [](OrcaStream::ChunkStream& cs) { DataSerialiser ds(cs.GetMode() == OrcaStream::Mode::WRITING, cs.GetStream()); @@ -628,7 +630,7 @@ namespace OpenRCT2 }); } - void ReadWriteRestrictedObjectsChunk(OrcaStream& os) + void ReadWriteRestrictedObjectsChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::RESTRICTED_OBJECTS, [](OrcaStream::ChunkStream& cs) { auto& restrictedScenery = GetRestrictedScenery(); @@ -650,8 +652,9 @@ namespace OpenRCT2 }); } - void ReadWritePluginStorageChunk(OrcaStream& os) + void ReadWritePluginStorageChunk(GameState_t& gameState, OrcaStream& os) { + // TODO: Use the passed gameState instead of the global one. auto& park = GetContext()->GetGameState()->GetPark(); if (os.GetMode() == OrcaStream::Mode::WRITING) { @@ -775,7 +778,7 @@ namespace OpenRCT2 }); } - void ReadWriteClimateChunk(OrcaStream& os) + void ReadWriteClimateChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::CLIMATE, [](OrcaStream::ChunkStream& cs) { cs.ReadWrite(gClimate); @@ -792,9 +795,10 @@ namespace OpenRCT2 }); } - void ReadWriteParkChunk(OrcaStream& os) + void ReadWriteParkChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::PARK, [version = os.GetHeader().TargetVersion](OrcaStream::ChunkStream& cs) { + // TODO: Use the passed gameState instead of the global one. auto& park = GetContext()->GetGameState()->GetPark(); cs.ReadWrite(park.Name); cs.ReadWrite(gCash); @@ -937,7 +941,7 @@ namespace OpenRCT2 }); } - void ReadWriteResearchChunk(OrcaStream& os) + void ReadWriteResearchChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::RESEARCH, [](OrcaStream::ChunkStream& cs) { // Research status @@ -991,7 +995,7 @@ namespace OpenRCT2 cs.ReadWrite(item.category); } - void ReadWriteNotificationsChunk(OrcaStream& os) + void ReadWriteNotificationsChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::NOTIFICATIONS, [](OrcaStream::ChunkStream& cs) { if (cs.GetMode() == OrcaStream::Mode::READING) @@ -1047,7 +1051,7 @@ namespace OpenRCT2 } } - void ReadWriteTilesChunk(OrcaStream& os) + void ReadWriteTilesChunk(GameState_t& gameState, OrcaStream& os) { auto* pathToSurfaceMap = _pathToSurfaceMap; auto* pathToQueueSurfaceMap = _pathToQueueSurfaceMap; @@ -1061,6 +1065,7 @@ namespace OpenRCT2 if (cs.GetMode() == OrcaStream::Mode::READING) { + // TODO: Use the passed gameState instead of the global one. OpenRCT2::GetContext()->GetGameState()->InitAll(gMapSize); auto numElements = cs.Read(); @@ -1167,7 +1172,7 @@ namespace OpenRCT2 } } - void ReadWriteBannersChunk(OrcaStream& os) + void ReadWriteBannersChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::BANNERS, [&os](OrcaStream::ChunkStream& cs) { auto version = os.GetHeader().TargetVersion; @@ -1245,7 +1250,7 @@ namespace OpenRCT2 cs.ReadWrite(banner.position.y); } - void ReadWriteRidesChunk(OrcaStream& os) + void ReadWriteRidesChunk(GameState_t& gameState, OrcaStream& os) { const auto version = os.GetHeader().TargetVersion; os.ReadWriteChunk(ParkFileChunkType::RIDES, [this, &version](OrcaStream::ChunkStream& cs) { @@ -1987,7 +1992,7 @@ namespace OpenRCT2 template void ReadEntitiesOfTypes(OrcaStream& os, OrcaStream::ChunkStream& cs); - void ReadWriteEntitiesChunk(OrcaStream& os); + void ReadWriteEntitiesChunk(GameState_t& gameState, OrcaStream& os); static void ReadWriteStringTable(OrcaStream::ChunkStream& cs, std::string& value, const std::string_view lcode) { @@ -2488,7 +2493,7 @@ namespace OpenRCT2 (ReadEntitiesOfType(os, cs), ...); } - void ParkFile::ReadWriteEntitiesChunk(OrcaStream& os) + void ParkFile::ReadWriteEntitiesChunk(GameState_t& gameState, OrcaStream& os) { os.ReadWriteChunk(ParkFileChunkType::ENTITIES, [this, &os](OrcaStream::ChunkStream& cs) { if (cs.GetMode() == OrcaStream::Mode::READING) @@ -2513,17 +2518,17 @@ namespace OpenRCT2 } } // namespace OpenRCT2 -void ParkFileExporter::Export(std::string_view path) +void ParkFileExporter::Export(GameState_t& gameState, std::string_view path) { auto parkFile = std::make_unique(); - parkFile->Save(path); + parkFile->Save(gameState, path); } -void ParkFileExporter::Export(IStream& stream) +void ParkFileExporter::Export(GameState_t& gameState, IStream& stream) { auto parkFile = std::make_unique(); parkFile->ExportObjectsList = ExportObjectsList; - parkFile->Save(stream); + parkFile->Save(gameState, stream); } enum : uint32_t @@ -2533,7 +2538,7 @@ enum : uint32_t S6_SAVE_FLAG_AUTOMATIC = 1u << 31, }; -int32_t ScenarioSave(u8string_view path, int32_t flags) +int32_t ScenarioSave(GameState_t& gameState, u8string_view path, int32_t flags) { if (flags & S6_SAVE_FLAG_SCENARIO) { @@ -2570,7 +2575,7 @@ int32_t ScenarioSave(u8string_view path, int32_t flags) { // s6exporter->SaveGame(path); } - parkFile->Save(path); + parkFile->Save(gameState, path); result = true; } catch (const std::exception& e) @@ -2658,9 +2663,9 @@ public: return result; } - void Import() override + void Import(GameState_t& gameState) override { - _parkFile->Import(); + _parkFile->Import(gameState); ResearchDetermineFirstOfType(); GameFixSaveVars(); } diff --git a/src/openrct2/park/ParkFile.h b/src/openrct2/park/ParkFile.h index 0186115de4..3aef7d103b 100644 --- a/src/openrct2/park/ParkFile.h +++ b/src/openrct2/park/ParkFile.h @@ -8,6 +8,8 @@ struct ObjectRepositoryItem; namespace OpenRCT2 { + struct GameState_t; + // Current version that is saved. constexpr uint32_t PARK_FILE_CURRENT_VERSION = 33; @@ -28,6 +30,6 @@ class ParkFileExporter public: std::vector ExportObjectsList; - void Export(std::string_view path); - void Export(OpenRCT2::IStream& stream); + void Export(OpenRCT2::GameState_t& gameState, std::string_view path); + void Export(OpenRCT2::GameState_t& gameState, OpenRCT2::IStream& stream); }; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 76565ba306..3098fcc379 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -169,7 +169,7 @@ namespace RCT1 return ParkLoadResult(GetRequiredObjects()); } - void Import() override + void Import(GameState_t& gameState) override { Initialise(); @@ -183,7 +183,7 @@ namespace RCT1 ImportFinance(); ImportResearch(); ImportParkName(); - ImportParkFlags(); + ImportParkFlags(gameState); ImportClimate(); ImportScenarioNameDetails(); ImportScenarioObjective(); @@ -2118,10 +2118,10 @@ namespace RCT1 park.Name = std::move(parkName); } - void ImportParkFlags() + void ImportParkFlags(GameState_t& gameState) { // Date and srand - GetGameState().CurrentTicks = _s4.Ticks; + gameState.CurrentTicks = _s4.Ticks; ScenarioRandSeed(_s4.RandomA, _s4.RandomB); GetContext()->GetGameState()->SetDate(Date(_s4.Month, _s4.Day)); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index a3e53fcbd1..321a26f893 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -227,7 +227,7 @@ namespace RCT2 return false; } - void Import() override + void Import(GameState_t& gameState) override { Initialise(); @@ -252,7 +252,7 @@ namespace RCT2 } OpenRCT2::GetContext()->GetGameState()->SetDate(OpenRCT2::Date(_s6.ElapsedMonths, _s6.CurrentDay)); - GetGameState().CurrentTicks = _s6.GameTicks1; + gameState.CurrentTicks = _s6.GameTicks1; ScenarioRandSeed(_s6.ScenarioSrand0, _s6.ScenarioSrand1); diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index a9132d15d3..66421c26b4 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -25,6 +25,11 @@ struct ResultWithMessage; using random_engine_t = Random::RCT2::Engine; +namespace OpenRCT2 +{ + struct GameState_t; +} + enum { SCENARIO_FLAGS_VISIBLE = (1 << 0), @@ -184,7 +189,7 @@ random_engine_t::result_type ScenarioRand(); uint32_t ScenarioRandMax(uint32_t max); ResultWithMessage ScenarioPrepareForSave(); -int32_t ScenarioSave(u8string_view path, int32_t flags); +int32_t ScenarioSave(OpenRCT2::GameState_t& gameState, u8string_view path, int32_t flags); void ScenarioFailure(); void ScenarioSuccess(); void ScenarioSuccessSubmitName(const char* name); diff --git a/test/tests/PlayTests.cpp b/test/tests/PlayTests.cpp index 9fab404ae8..60494ea385 100644 --- a/test/tests/PlayTests.cpp +++ b/test/tests/PlayTests.cpp @@ -49,7 +49,10 @@ static std::unique_ptr localStartGame(const std::string& parkPath) auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadSavedGame(parkPath.c_str(), false); context->GetObjectManager().LoadObjects(loadResult.RequiredObjects); - importer->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); ResetEntitySpatialIndices(); diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp index 754716898f..4a49064e25 100644 --- a/test/tests/S6ImportExportTests.cpp +++ b/test/tests/S6ImportExportTests.cpp @@ -83,7 +83,10 @@ static bool ImportS6(MemoryStream& stream, std::unique_ptr& context, b auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(&stream, false); objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); GameInit(retainSpatialIndices); @@ -99,7 +102,10 @@ static bool ImportPark(MemoryStream& stream, std::unique_ptr& context, auto importer = ParkImporter::CreateParkFile(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(&stream, false); objManager.LoadObjects(loadResult.RequiredObjects); - importer->Import(); + + // TODO: Have a separate GameState and exchange once loaded. + auto& gameState = GetGameState(); + importer->Import(gameState); GameInit(retainSpatialIndices); @@ -112,7 +118,9 @@ static bool ExportSave(MemoryStream& stream, std::unique_ptr& context) auto exporter = std::make_unique(); exporter->ExportObjectsList = objManager.GetPackableObjects(); - exporter->Export(stream); + + auto& gameState = GetGameState(); + exporter->Export(gameState, stream); return true; }