Sugarcube 2 keep state after refresh

tweego, version 2.1.1+81d1d71 (2020-02-25T07:09:26Z) [darwin/amd64] “name”:“SugarCube”,“version”:“2.36.1”

I’m using direct access to the State.variables data structure to persist data, and to make autosave/load work, and to avoid data loss on refresh. Simplified example:

SETUP.TWEE
:: StoryScript [script]
/* Used to set up all normal, non-SugarCube dependant JS */
console.log("StoryScript started");

/* Aliases for access to SugarCube functions/variables, as they aren't available normally in pure js */
window.s = window.s || {}
window.s.setup = function (engine, state) {
    window.s.Engine = engine;
    window.s.State = state;
    window.s.v = state.variables;
}

importScripts(
  ["js/myjs.js"]
);

:: StoryInit
/* Used to set up all SugarCube-dependants*/
<<script>>
  window.s.setup(Engine, State);
<</script>>

:: Game
<div id="resource"/>
<div onclick="window.c.doActivity()">Do activity</div>
<script>
  var resourceContainer = document.getElementById('resource');
  var resource = window.s.v.resource;
  resourceContainer.innerHTML += '<div class="resource-entry">Resource count: ' + resource + '</div>';
</script>

JS FILE
window.c = window.c || {}
window.c.doActivity = function () {
    window.s.v.resource += 10;
    window.s.Engine.show();
};

My understanding is that the data should remain on refresh but I end up with errors when I refresh the page, on the resource reference, as undefined. Any tips on where I’m going wrong?

Thanks!

is this refresh like you’re in the same savefile and you just refresh the page? I think that should be stored in (edit) session storage and not be an issue from passage to passage. not sure about when it’s all in one big passage though (though that’s not something you should be doing anyway)

edit: also

https://www.motoslave.net/sugarcube/2/docs/#save-api-autosave

You don’t show where you’re setting $resource to an initial value. You are doing that, yes? I ask because uninitialized values are undefined.

If you’re not initializing it before attempting to use it, then that’s your problem.

Additionally. Unless storage is completely unavailable, in which case SugarCube should refuse to run, you don’t lose data on refresh in the first place because SugarCube keeps track of the current playthrough session—you don’t have to do anything bizarre to enable this. This is separate from saves, which exist to persist playthroughs across multiple sessions.

Also. Why are you using importScripts() to load an external JavaScript file if you’re using Tweego? That doesn’t make a lot of sense on first blush as Tweego can compile loose *.js files into your project—either internally or exterally to SugarCube’s own scope.

2 Likes

Thank you for replying. I didn’t include initial setting of the resource but you can consider it initialised when we enter the Game passage (I also missed the Start passage and basic button to take us to the Game passage).

I also tested with the web developer console, setting window.SugarCube.State.variables.cows = "cows" and then refreshing the page and retrieving window.SugarCube.State.variables but it returns {}.

Hence I’m confused. I have another (more complex) project where caching is working fine, but I can’t see where the difference lies.

Also, I’m using importScripts since I need them ordered. Not sure if that’s normal or not, but I have some initialisation done in js files. Is this not the idiomatic way?

Actually I’ve just managed to resolve it. After I changed from using importScripts to tweego folder includes (tweego src js/init js/control js/game js/ui -o story.html --watch) I was testing the State.variables caching again and ended up finding that for some reason, the js alias I set up (window.s.v = State.variables) was the issue. I’m still not sure why it was an issue, given the initialisation js still executes…

Also I remembered that I had discussed the importScripts thing here: ImportScripts order of import - #5 by Atawf but never got back to it.

Thank you for your answers!

Edit: So turns out it still isn’t working. The thing that saves data in the State.variables is progressing to another moment/passage. Whereas, I’m just refreshing the passage using Engine.show(). Is this a bad way? Should I be using play([currentPassageName])?

Edit2: So yes, using Engine.play with the current passage does work as way of persisting new data while remaining in the same passage. Please still do let me know if this is bad for any reason (e.g. unexpected consequences). I’m aware of impact on history though.