Пример #1
0
    /// <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);
            }
        }
    }
Пример #2
0
    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);
            }
        }
    }
Пример #3
0
    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);
    }
Пример #4
0
    public static SaveInformation LoadJustInfoFromSave(string saveName)
    {
        var target = SaveFileInfo.SaveNameToPath(saveName);

        var(info, _, _) = LoadFromFile(target, true, false, false, null);

        return(info);
    }
Пример #5
0
    /// <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);
    }
Пример #6
0
    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);
    }
Пример #7
0
    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());
        }
    }
Пример #8
0
    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);
    }
Пример #9
0
    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;
        }
    }