RubbleGames

Problem with local storage save

Recommended Posts

Hi, I've just released a game to Newgrounds and I'm getting a few reports of problems that seem to come from the save data but only on Newgrounds, the same players can play the game on my site without problems.

I'm storing save variables as a json string in local storage and some players seem to be pulling save data from local storage despite never having played the game before. I have a generic name for the save object and I was wondering if this could be the problem? Maybe I'm getting save data from other games that have also used the same generic name? Has anyone come across anything like this before?

See my other post for links and an instance of the problem:

 

Share this post


Link to post
Share on other sites

I assume you mean this page: Zombie Cannon Attack! on Newgrounds.

Your game on Newgrounds doesn't work either on my laptop using Chrome, it gives this error:

Quote

TypeError: Cannot read property 'hordeSpeed' of null

I've looked at the JavaScript code and it seems to me the problem is the way you check to see if there are already any settings in the localstorage. If I understand correctly, the local storage is specific to a page (or URL) and I suspect that Newgrounds page also uses the localstorage for the menus and ads banners and such. So the localStorage.length is higher than zero, but your game's "save" key does not exist yet.

if (localStorage.length > 0) {
    var t = localStorage.getItem("save");
    saveObject = JSON.parse(t);
    null == saveObject.hordeSpeed||void 0 == saveObject.hordeSpeed||(power = saveObject.power;
    infectSlow = saveObject.infectSlow;
    bounceSlow = saveObject.bounceSlow;
    //etc.

I would change that to something like this:

// use a game specific keyname
var t = localStorage.getItem("zombies_save");

// error checking, localstorage might not exist yet at first time start up
try {
    saveObject = JSON.parse(t);
} catch (e) {
    // if an error occurs, set default values
    saveObject = {
        "hordeSpeed":10,
        "infectSlow":true,
        "bounceSlow":false,
        //etc.
    };
};

 

Share this post


Link to post
Share on other sites

Hi, thanks a lot for this. I'm assuming that changing the keyname now will cause problems for people who have an existing save? I've attempted a workaround where I check if the save object contains something specific to my game, that seems to have caused the error you saw so I've tried something else that hopefully works. If anyone else can check for me that would be really helpful.

Share this post


Link to post
Share on other sites

It's the underlying domain (uploads.ungrounded.net) that newgrounds use, seemed to be a shared domain for all games (I fired up another couple) so yeah, you'll all be potentially sharing storage data, wow! Security anybody? Aren't non-isolated environments fun?

In any case, not sure if I've played a game on newgrounds before (probably have) but my storage for uploads.ungrounded.net (where your game comes from) looks like:

Screen Shot 2017-08-10 at 09.21.50.png

I get the same hordeSpeed error as BdR so the game doesn't load so I'm guessing its not you setting those values in storage, so it has been someone else.

The fix BdR suggests should fix your problem and you wouldn't have to change the keys you're using, unless you are worried that other games might be sharing those keys, and, yes, changing the key would be a breaking change for any existing users you have with saved stuff.

Share this post


Link to post
Share on other sites

No, from his response just change "zombie_save" to "save", the problem is that you're assuming that is localStorage.length > 0 then "save" will be there and correct, however, from my screenshot localStorage.length will equal 5, so, in your code, you'll carry on and get `null` returned from getting the item from localStorage, which you then try to access with saveObject.hordeSpeed which will blow up.

Infact, BdR's answer isn't quite going to work for you either as JSON.parse(null) won't error, it'll just return null (as you should expect) so you'll never set the default values.

However, you should go ahead and change the key to something more specific to you (I'd suggest zombie_save isn't unique enough to be safe), the problem you're having is that some people maybe already have a "save" key in their localStorage as you said some peeps seem to be able to playing as if they had previously saved.

In short, it sounds like you might have two problems:

* Your key isn't unique to you as games on newgrounds seem to share a domain and hence share a localStorage -> solved by making the key really very unique (i.e. 'rubble_zombies_save_XYZ')

* You're not checking carefully enough that your saved variable is actually what you expect

To solve problem two you could do something like the following to populate with default values:

const defaultSaveState = {
  hordeSpeed: 10,
  level: 1,
  coins: 0
}

function getSaveState (key) {
  const savedObject = localStorage.getItem(key)
  return Object.assign({}, defaultSaveState, JSON.parse(savedObject))
}

// Call it
const state = getSaveState('rubbles_super_zombie_game_save')
console.log(state)

note: old browsers need a polyfill for Object.assign, if you're transpiling you can use object spread to make this even more succinct

The `getSavedState` function grabs a certain key from local storage, if it does not exist it'll be `null` (I'm guessing this happens in all browsers, might not though), we then use Object.assign to clone the default state and then overlay savedObject on top of it, meaning that if the savedObject contains `level: 3` then your resultant object will also contain that, check out how Object.assign works if its not clear.

Note the initial empty object parameter to Object.assign, this is important to ensure you don't try to mutate the defaultSaveState, even though it is a `const` it isn't immutable in JS. 

Your savedObject might be `null` but JSON.parse(null) also evaluates to `null` and Object.assign can handle assigning `null` (it becomes ignored) so you know that the object returned from `getSaveState` is going to be of the right form and populated either with defaults or with details from a previous save.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.