tmedwards / sugarcube-2

SugarCube is a free (gratis and libre) story format for Twine/Twee.
https://www.motoslave.net/sugarcube/2/
BSD 2-Clause "Simplified" License
177 stars 41 forks source link

Add the ability to export a specific save slot #248

Closed BawdyInkSlinger closed 1 year ago

BawdyInkSlinger commented 1 year ago

Is your feature request related to a problem? I'm customizing my own save dialog and I would like to create an export button for each slot: image

As far as I can tell, the API does not provide a way to export other saves, only your current state/save.

  1. http://www.motoslave.net/sugarcube/2/docs/#save-api-method-serialize uses your current state/save.
  2. http://www.motoslave.net/sugarcube/2/docs/#save-api-method-export uses your current state/save.
  3. http://www.motoslave.net/sugarcube/2/docs/#save-api-method-slots-get can get a save separate from your own, but I don't see a function I can pass it into to get its serialized form.
  4. http://www.motoslave.net/sugarcube/2/docs/#save-api-method-get returns an array of saves separate from your own, but I don't see a function I can pass it into to get its serialized form.

Describe the solution you'd like. I'd like a way to export a save I'm not currently playing.

Perhaps http://www.motoslave.net/sugarcube/2/docs/#save-api-method-export could be modified to add a new optional, numeric parameter: slot.

Perhaps http://www.motoslave.net/sugarcube/2/docs/#save-api-method-serialize could be modified to add a new optional, numeric parameter: slot.

Describe alternatives you've considered. If I browse the source code there might be an undocumented feature that allows me to build this functionality, but I wouldn't consider that a stable solution. Perhaps I can copy Save.serialize and/or Save.export into my own project and modify it for this purpose.

Maybe there is already a way to achieve this in the API and I just haven't found it.

Otherwise, I think the only alternative for me is to not build this feature.

Additional context. Discord discussion starts here: https://discord.com/channels/389867840406159362/389868418855075840/1124070615066886318

tmedwards commented 1 year ago

Duplicate of issue #190.

tmedwards commented 1 year ago

From the current alpha documentation:


Save.browser.export(filename)

Exports all browser saves, both auto and slot, as a bundle.

History:

Parameters:

Examples:

Attempt to export all browser saves using the story's name as the base filename.

Save.browser.export(Story.name);

Save.browser.import(event)Promise

Attempts to restore browser saves from an exported bundle. Returns a Promise that either resolves or rejects with an error describing the failure.

Note: This method must be used as, or be called by, the change event handler of an <input type="file"> element.

Warning: All existing browser saves will be deleted as part of restoring the exported bundle.

History:

Parameters:

Examples:

Most common basic usage.

Use the method as the event handler for an <input type="file"> element.

jQuery(document.createElement('input'))
    .prop({
        id   : 'saves-browser-import-file',
        name : 'saves-browser-import-file',
        type : 'file'
    })
    .on('change', Save.browser.import);

In case you need to do more than simply restoring the exported bundle, you may call the method from the event handler of an <input type="file"> element.

jQuery(document.createElement('input'))
    .prop({
        id   : 'saves-browser-import-file',
        name : 'saves-browser-import-file',
        type : 'file'
    })
    .on('change', function (ev) {
        // Anything you need to do before the restoration

        // You must pass in the event when calling Save.import() manually
        Save.browser.import(ev);

        // Anything you need to do after the restoration
    });

BawdyInkSlinger commented 1 year ago

I just noticed a typo in the title of this issue. Sorry for the confusion. 😬 I was asking for an API to export a specific slot, not all of them at once. Here's a less ambiguous picture of the UI I'd like to build.

image

I don't think this is possible in the current or future API. That said, a single button that exports them all isn't that far off; I could do that instead.

greyelf commented 1 year ago

@BawdyInkSlinger

I don't think this is possible in the current or future API.

The end-user can currently simulate the equivalent of your "Save a specific slot to disk" functionality by simply: first using that specific slot's Load button to load that save into memory; and then using the Save dialog's Save to Disk button to save the current state of History to file.

BawdyInkSlinger commented 2 months ago

@tmedwards

Duplicate of issue #190.

I've edited my original post for clarity. I'm requesting a way to export a single slot without exporting the others.

I couldn't find this mentioned in #190 so I was wondering if this issue could be reopened?

tmedwards commented 2 months ago

No. You can already save to disk.

If you have an existing save that you want to export, then loading it and choosing to save save to disk is not an onerous way to achieve your goal.

BawdyInkSlinger commented 2 months ago

If you have an existing save that you want to export[a], then loading it[b] and choosing to save save to disk[c] is not an onerous way to achieve your goal.

I'm not clear on how to perform "c" because I don't see a way to save a slot, I only see ways to save all slots. Will the upcoming Save.disk.save(filename [, metadata]) export the current slot? I didn't realize that. I've submitted a PR to add that to the wording: https://github.com/tmedwards/sugarcube-2/pull/307

greyelf commented 2 months ago

@BawdyInkSlinger

I only see ways to save all slots.

That method persists the current state of Progress History to disk, not the state currently stored in the "filled" slots. eg. it works the same way that the slot based saves do, except to a file.

Which is why TME's previous suggestion included the 1st step...

[a], then loading it

BawdyInkSlinger commented 2 months ago

@greyelf

Which is why TME's previous suggestion included the 1st step...

[a], then loading it

Ah, that makes sense. Sorry for not picking up on that.