/***************************************************************************** * Copyright (c) 2014-2019 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ #include "TestData.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace OpenRCT2; // Copied from Network.cpp static bool LoadMap(IStream* stream) { bool result = false; try { auto context = GetContext(); auto& objManager = context->GetObjectManager(); auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(stream, false); objManager.LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); importer->Import(); sprite_position_tween_reset(); // Read checksum [[maybe_unused]] uint32_t checksum = stream->ReadValue(); // Read other data not in normal save files stream->Read(gSpriteSpatialIndex, 0x10001 * sizeof(uint16_t)); gGamePaused = stream->ReadValue(); _guestGenerationProbability = stream->ReadValue(); _suggestedGuestMaximum = stream->ReadValue(); gCheatsSandboxMode = stream->ReadValue() != 0; gCheatsDisableClearanceChecks = stream->ReadValue() != 0; gCheatsDisableSupportLimits = stream->ReadValue() != 0; gCheatsDisableTrainLengthLimit = stream->ReadValue() != 0; gCheatsEnableChainLiftOnAllTrack = stream->ReadValue() != 0; gCheatsShowAllOperatingModes = stream->ReadValue() != 0; gCheatsShowVehiclesFromOtherTrackTypes = stream->ReadValue() != 0; gCheatsFastLiftHill = stream->ReadValue() != 0; gCheatsDisableBrakesFailure = stream->ReadValue() != 0; gCheatsDisableAllBreakdowns = stream->ReadValue() != 0; gCheatsBuildInPauseMode = stream->ReadValue() != 0; gCheatsIgnoreRideIntensity = stream->ReadValue() != 0; gCheatsDisableVandalism = stream->ReadValue() != 0; gCheatsDisableLittering = stream->ReadValue() != 0; gCheatsNeverendingMarketing = stream->ReadValue() != 0; gCheatsFreezeWeather = stream->ReadValue() != 0; gCheatsDisablePlantAging = stream->ReadValue() != 0; gCheatsAllowArbitraryRideTypeChanges = stream->ReadValue() != 0; gCheatsDisableRideValueAging = stream->ReadValue() != 0; gConfigGeneral.show_real_names_of_guests = stream->ReadValue() != 0; gCheatsIgnoreResearchStatus = stream->ReadValue() != 0; result = true; } catch (const std::exception&) { } return result; } // Copied from Network.cpp static bool SaveMap(IStream* stream, const std::vector& objects) { bool result = false; viewport_set_saved_view(); try { auto s6exporter = std::make_unique(); s6exporter->ExportObjectsList = objects; s6exporter->Export(); s6exporter->SaveGame(stream); // Write other data not in normal save files stream->Write(gSpriteSpatialIndex, 0x10001 * sizeof(uint16_t)); stream->WriteValue(gGamePaused); stream->WriteValue(_guestGenerationProbability); stream->WriteValue(_suggestedGuestMaximum); stream->WriteValue(gCheatsSandboxMode); stream->WriteValue(gCheatsDisableClearanceChecks); stream->WriteValue(gCheatsDisableSupportLimits); stream->WriteValue(gCheatsDisableTrainLengthLimit); stream->WriteValue(gCheatsEnableChainLiftOnAllTrack); stream->WriteValue(gCheatsShowAllOperatingModes); stream->WriteValue(gCheatsShowVehiclesFromOtherTrackTypes); stream->WriteValue(gCheatsFastLiftHill); stream->WriteValue(gCheatsDisableBrakesFailure); stream->WriteValue(gCheatsDisableAllBreakdowns); stream->WriteValue(gCheatsBuildInPauseMode); stream->WriteValue(gCheatsIgnoreRideIntensity); stream->WriteValue(gCheatsDisableVandalism); stream->WriteValue(gCheatsDisableLittering); stream->WriteValue(gCheatsNeverendingMarketing); stream->WriteValue(gCheatsFreezeWeather); stream->WriteValue(gCheatsDisablePlantAging); stream->WriteValue(gCheatsAllowArbitraryRideTypeChanges); stream->WriteValue(gCheatsDisableRideValueAging); stream->WriteValue(gConfigGeneral.show_real_names_of_guests); stream->WriteValue(gCheatsIgnoreResearchStatus); result = true; } catch (const std::exception&) { } return result; } // Special version of game_load_init which does not call reset_sprite_spatial_index // This is conditionally done in game_load_init for when we are not a client. static void network_game_load_init() { gScreenFlags = SCREEN_FLAGS_PLAYING; reset_all_sprite_quadrant_placements(); scenery_set_default_placement_configuration(); gWindowUpdateTicks = 0; load_palette(); gGameSpeed = 1; } TEST(NetworkLoadSave, all) { std::string path = TestData::GetParkPath("bpb.sv6"); gOpenRCT2Headless = true; gOpenRCT2NoGraphics = true; core_init(); auto mainContext = CreateContext(); bool initialised = mainContext->Initialise(); ASSERT_TRUE(initialised); auto& objManager = mainContext->GetObjectManager(); // Load initial park data. { auto importer = ParkImporter::CreateS6(mainContext->GetObjectRepository()); auto loadResult = importer->Load(path.c_str()); objManager.LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); importer->Import(); game_load_init(); } // Advance the park for 100 ticks to have changes in the park. { for (int i = 0; i < 100; i++) { mainContext->GetGameState()->UpdateLogic(); } } MemoryStream savedPark; rct_sprite_checksum checksumSave; rct_sprite_checksum checksumLoad; // Save park. { std::vector objects = objManager.GetPackableObjects(); bool saveResult = SaveMap(&savedPark, objects); ASSERT_TRUE(saveResult); checksumSave = sprite_checksum(); } // Import the exported version. { savedPark.SetPosition(0); bool loadResult = LoadMap(&savedPark); ASSERT_TRUE(loadResult); network_game_load_init(); checksumLoad = sprite_checksum(); } ASSERT_EQ(checksumSave.ToString(), checksumLoad.ToString()); SUCCEED(); }