bool CloudySaveManagerImpl::Cloudy_SaveGameToSlot(USaveGame* SaveGameObject, const FString& SlotName, const int32 UserIndex, const int32 PCID) { bool bSuccess = false; // Appends the player controller ID to the save file, // so that the split screen players do not overwrite 1 save file. FString NewSlotName = SlotName + "-" + FString::FromInt(PCID); ISaveGameSystem* SaveSystem = IPlatformFeaturesModule::Get().GetSaveGameSystem(); // If we have a system and an object to save and a save name... if (SaveSystem && (SaveGameObject != NULL) && (NewSlotName.Len() > 0)) { TArray<uint8> ObjectBytes; FMemoryWriter MemoryWriter(ObjectBytes, true); // write file type tag. identifies this file type and indicates it's using proper versioning // since older UE4 versions did not version this data. int32 FileTypeTag = UE4_SAVEGAME_FILE_TYPE_TAG; MemoryWriter << FileTypeTag; // Write version for this file format int32 SavegameFileVersion = UE4_SAVEGAME_FILE_VERSION; MemoryWriter << SavegameFileVersion; // Write out engine and UE4 version information MemoryWriter << GPackageFileUE4Version; FEngineVersion SavedEngineVersion = GEngineVersion; MemoryWriter << SavedEngineVersion; // Write the class name so we know what class to load to FString SaveGameClassName = SaveGameObject->GetClass()->GetName(); MemoryWriter << SaveGameClassName; // Then save the object state, replacing object refs and names with strings FObjectAndNameAsStringProxyArchive Ar(MemoryWriter, false); SaveGameObject->Serialize(Ar); // Stuff that data into the save system with the desired file name SaveSystem->SaveGame(false, *NewSlotName, UserIndex, ObjectBytes); bSuccess = ICloudyWebAPI::Get().UploadFile(NewSlotName, PCID); } return bSuccess; }
/** * Saves and loads a savegame file * * @param Parameters - Unused for this test * @return TRUE if the test was successful, FALSE otherwise */ bool FSaveGameTest::RunTest(const FString& Parameters) { // automation save name const TCHAR* SaveName = TEXT("AutomationSaveTest"); uint32 SavedData = 99; // the blob we are going to write out TArray<uint8> Blob; FMemoryWriter WriteAr(Blob); WriteAr << SavedData; // get the platform's save system ISaveGameSystem* Save = IPlatformFeaturesModule::Get().GetSaveGameSystem(); // write it out if (Save->SaveGame(false, SaveName, 0, Blob) == false) { return false; } // make sure it was written if (Save->DoesSaveGameExist(SaveName, 0) == false) { return false; } // read it back in Blob.Empty(); if (Save->LoadGame(false, SaveName, 0, Blob) == false) { return false; } // make sure it's the same data FMemoryReader ReadAr(Blob); uint32 LoadedData; ReadAr << LoadedData; // try to delete it (not all platforms can) if (Save->DeleteGame(false, SaveName, 0)) { // make sure it's no longer there if (Save->DoesSaveGameExist(SaveName, 0) == true) { return false; } } return LoadedData == SavedData; }
USaveGame* CloudySaveManagerImpl::Cloudy_LoadGameFromSlot(const FString& SlotName, const int32 UserIndex, const int32 PCID) { // Load from CloudyWeb, write it to default save location. ICloudyWebAPI::Get().DownloadFile(SlotName, PCID); // Appends the player controller ID to the save file, // so that the split screen players do not overwrite 1 save file. FString NewSlotName = SlotName + "-" + FString::FromInt(PCID); USaveGame* OutSaveGameObject = NULL; ISaveGameSystem* SaveSystem = IPlatformFeaturesModule::Get().GetSaveGameSystem(); // If we have a save system and a valid name.. if (SaveSystem && (NewSlotName.Len() > 0)) { // Load raw data from slot TArray<uint8> ObjectBytes; bool bSuccess = SaveSystem->LoadGame(false, *NewSlotName, UserIndex, ObjectBytes); if (bSuccess) { FMemoryReader MemoryReader(ObjectBytes, true); int32 FileTypeTag; MemoryReader << FileTypeTag; int32 SavegameFileVersion; if (FileTypeTag != UE4_SAVEGAME_FILE_TYPE_TAG) { // this is an old saved game, back up the file pointer to the beginning and assume version 1 MemoryReader.Seek(0); SavegameFileVersion = 1; // Note for 4.8 and beyond: if you get a crash loading a pre-4.8 version of your savegame file and // you don't want to delete it, try uncommenting these lines and changing them to use the version // information from your previous build. Then load and resave your savegame file. //MemoryReader.SetUE4Ver(MyPreviousUE4Version); // @see GPackageFileUE4Version //MemoryReader.SetEngineVer(MyPreviousEngineVersion); // @see FEngineVersion::Current() } else { // Read version for this file format MemoryReader << SavegameFileVersion; // Read engine and UE4 version information int32 SavedUE4Version; MemoryReader << SavedUE4Version; FEngineVersion SavedEngineVersion; MemoryReader << SavedEngineVersion; MemoryReader.SetUE4Ver(SavedUE4Version); MemoryReader.SetEngineVer(SavedEngineVersion); } // Get the class name FString SaveGameClassName; MemoryReader << SaveGameClassName; // Try and find it, and failing that, load it UClass* SaveGameClass = FindObject<UClass>(ANY_PACKAGE, *SaveGameClassName); if (SaveGameClass == NULL) { SaveGameClass = LoadObject<UClass>(NULL, *SaveGameClassName); } // If we have a class, try and load it. if (SaveGameClass != NULL) { OutSaveGameObject = NewObject<USaveGame>(GetTransientPackage(), SaveGameClass); FObjectAndNameAsStringProxyArchive Ar(MemoryReader, true); OutSaveGameObject->Serialize(Ar); } UE_LOG(CloudySaveManagerLog, Warning, TEXT("Game loaded successfully.")); } } return OutSaveGameObject; }