/// <summary> /// Writes this save to disk. /// </summary> /// <remarks> /// In order to save the screenshot as png this needs to save it to a temporary file on disk. /// </remarks> public void SaveToFile() { FileHelpers.MakeSureDirectoryExists(Constants.SAVE_FOLDER); var target = SaveFileInfo.SaveNameToPath(Name); var justInfo = ThriveJsonConverter.Instance.SerializeObject(Info); var serialized = ThriveJsonConverter.Instance.SerializeObject(this); string tempScreenshot = null; if (Screenshot != null) { tempScreenshot = PathUtils.Join(Constants.SAVE_FOLDER, "tmp.png"); if (Screenshot.SavePng(tempScreenshot) != Error.Ok) { GD.PrintErr("Failed to save screenshot for inclusion in save"); Screenshot = null; tempScreenshot = null; } } try { WriteDataToSaveFile(target, justInfo, serialized, tempScreenshot); } finally { // Remove the temp file if (tempScreenshot != null) { FileHelpers.DeleteFile(tempScreenshot); } } }
private static void WriteRawSaveDataToFile(SaveInformation saveInfo, string saveContent, Image screenshot, string saveName) { FileHelpers.MakeSureDirectoryExists(Constants.SAVE_FOLDER); var target = SaveFileInfo.SaveNameToPath(saveName); var justInfo = ThriveJsonConverter.Instance.SerializeObject(saveInfo); string tempScreenshot = null; if (screenshot != null) { // TODO: if in the future Godot allows converting images to in-memory PNGs that should be used here tempScreenshot = PathUtils.Join(Constants.SAVE_FOLDER, "tmp.png"); if (screenshot.SavePng(tempScreenshot) != Error.Ok) { GD.PrintErr("Failed to save screenshot for inclusion in save"); tempScreenshot = null; } } try { WriteDataToSaveFile(target, justInfo, saveContent, tempScreenshot); } finally { // Remove the temp file if (tempScreenshot != null) { FileHelpers.DeleteFile(tempScreenshot); } } }
public static (SaveInformation Info, JObject SaveObject, Image Screenshot) LoadJSONStructureFromFile( string saveName) { var target = SaveFileInfo.SaveNameToPath(saveName); var(infoStr, saveStr, screenshotData) = LoadDataFromFile(target, true, true, true); if (string.IsNullOrEmpty(infoStr)) { throw new IOException("couldn't find info content in save"); } if (string.IsNullOrEmpty(saveStr)) { throw new IOException("couldn't find save content in save file"); } var infoResult = ThriveJsonConverter.Instance.DeserializeObject <SaveInformation>(infoStr); // Don't use the normal deserialization as we don't want to actually create the game state, instead we want // a JSON structure var saveResult = JObject.Parse(saveStr); var imageResult = new Image(); if (screenshotData?.Length > 0) { imageResult.LoadPngFromBuffer(screenshotData); } return(infoResult, saveResult, imageResult); }
public static SaveInformation LoadJustInfoFromSave(string saveName) { var target = SaveFileInfo.SaveNameToPath(saveName); var(info, _, _) = LoadFromFile(target, true, false, false, null); return(info); }
/// <summary> /// Loads a save from a file or throws an exception /// </summary> /// <param name="saveName">The name of the save. This is not the full path.</param> /// <param name="readFinished"> /// A callback that is called when reading data has finished and creating objects start. /// </param> /// <returns>The loaded save</returns> public static Save LoadFromFile(string saveName, Action readFinished = null) { var target = SaveFileInfo.SaveNameToPath(saveName); var(_, save, screenshot) = LoadFromFile(target, false, true, true, readFinished); // Info is already contained in save so it doesn't need to be loaded and assigned here save.Screenshot = screenshot; return(save); }
public static Save LoadInfoAndScreenshotFromSave(string saveName) { var target = SaveFileInfo.SaveNameToPath(saveName); var(info, _, screenshot) = LoadFromFile(target, true, false, true, null); var save = new Save(); save.Name = saveName; save.Info = info; save.Screenshot = screenshot; return(save); }
public static SaveInformation LoadJustInfoFromSave(string saveName) { var target = SaveFileInfo.SaveNameToPath(saveName); try { var(info, _, _) = LoadFromFile(target, true, false, false, null); return(info); } catch (Exception e) { GD.PrintErr($"Failed to load save info from ${saveName}, error: ${e}"); return(SaveInformation.CreateInvalid()); } }
public static Save LoadInfoAndScreenshotFromSave(string saveName) { var target = SaveFileInfo.SaveNameToPath(saveName); var save = new Save { Name = saveName }; try { var(info, _, screenshot) = LoadFromFile(target, true, false, true, null); save.Info = info; save.Screenshot = screenshot; } catch (Exception e) { GD.PrintErr($"Failed to load save info and screenshot from ${saveName}, error: ${e}"); save.Info = SaveInformation.CreateInvalid(); save.Screenshot = null; } return(save); }
public static void PerformSaveUpgrade(SaveInformation saveInfo, string inputSave, bool backup = true, string?targetVersion = null) { targetVersion ??= Constants.Version; if (saveInfo.ThriveVersion == targetVersion) { throw new ArgumentException("Can't upgrade a save that is already at current version"); } string fromSave; string toSave; if (backup) { if (IsSaveABackup(inputSave)) { // Already backed up file fromSave = inputSave; toSave = RemoveBackupSuffix(inputSave); } else { toSave = inputSave; fromSave = inputSave.Remove( inputSave.IndexOf(Constants.SAVE_EXTENSION_WITH_DOT, StringComparison.InvariantCulture), Constants.SAVE_EXTENSION_WITH_DOT.Length) + Constants.SAVE_BACKUP_SUFFIX; using var folder = new Directory(); if (folder.Rename(SaveFileInfo.SaveNameToPath(toSave), SaveFileInfo.SaveNameToPath(fromSave)) != Error.Ok) { throw new Exception("Failed to rename save to backup name"); } } } else { GD.Print("Not making a backup before upgrading a save"); fromSave = toSave = inputSave; } var fromVersion = saveInfo.ThriveVersion; GD.Print("Beginning save upgrade from version ", fromVersion, " from save: ", fromSave, " to save: ", toSave); while (true) { // Here we also need to do this hacky store thing fromVersion = saveInfo.ThriveVersion; var nextStep = FindPathToVersion(saveInfo, fromVersion, targetVersion); saveInfo.ThriveVersion = fromVersion; if (nextStep == null) { GD.Print("Upgrading finished, no steps remain"); break; } var upgradedVersion = nextStep.PerformUpgrade(saveInfo, fromSave, toSave); GD.Print("Performed upgrade step from ", fromVersion, " to ", upgradedVersion); if (saveInfo.ThriveVersion != upgradedVersion) { throw new Exception("Save info version not upgraded as expected"); } // After the first step the target save is upgraded in-place so we need to overwrite the old source fromSave = toSave; } }