Store data with stores

Hello everyone.

I launched a beta of my game and they asked me to enter access to google play and appStore to save game data.

I have never inserted this feature. I read the guide but I’m a little puzzled.

Anyone would have the source code that allows this to be done with a simple button on both platforms.I ask this because I would like to avoid stupid mistakes that could lead to reappraisal of the app from the store …

Who asked you?

Do you have some screen shots for context?

Rob

I had provided my mail I received the feedback.

I have been asked for various things, and one of them was what I asked.

In almost every game, however, it is now possible. A button that lets you go to google play to save your data. And the same service is also available for iOS. This is also often used to have more profiles of the same game on a device.

Is it clear what I need? Or did I explain it badly? I’m not native speaker…

“I launched a beta of my game and they asked me to enter access”

Are you saying “they” are your customers? Or is Google asking you to do this? That’s what I’m trying to figure out. I’ve never seen Google ask for this.

But I think I understand a little better. You want to be able to save your current game/data, possibly in a way that people can switch devices and resume play where they left off. Is that the question?

If so, you should create a table in your game that holds all of the data you want to save: current level, score, coins collected, etc., every thing you need to resume the game at some point. In the game I’m making you can’t resume in the middle of the level, but I let you resume at the last level you started. 

The general workflow when the game starts is to:

  1. Look to see if your saved data exists. If so load it and populate your save data table.

  2. If it does not, create your save data table and populate it with starting values for the first level of your game.

  3. When you make a change to any of those values, update the table and save the table.

You only need to load the table when the app first starts up from having been edited. If it’s just suspended it should return you to where you were. 

Once you have all of this in a single table, you can use various techniques to save that data. If you are only concerned about local saves, you can use something like the loadsave module here: https://github.com/robmiracle/Simple-Table-Load-Save-Functions-for-Corona-SDK

If you want to do cloud saves, then you can, but it will require you to do different things for Android and iOS. On iOS you would use our iCloud plugin. See: https://docs.coronalabs.com/plugin/iCloud/index.html

For Android you will use the GPGS plugin and use snapshots. See: https://docs.coronalabs.com/plugin/gpgs/snapshots/index.html

Rob

Okay then I’ll explain it better.

Yes, my customers have asked me this.

I have no problem saving game data in the phone(local). I already use the technique you described to save the data.

I save several files in the path:

system.DocumentsDirectory

To this point everything is perfect.

What you have recommended with iCloud is more or less what I need… However I was specifically asked to use access to the 2 stores.

To explain this use a video on a famous game:

Andoid: https://www.youtube.com/watch?v=_jYx60T3rhA

iOS     : https://www.youtube.com/watch?v=phZ6A9BMnDE

I believe there is a simple way to get the data that I save locally and save them to the store. (Following the acess of the user)

I hope I was clear. I apologize if initially I did not explain it well

That’s what I shared with you. For GPGS it’s called Snapshots. You can save various data types to GPGS and load them back as needed.  You do have to be logged in to GPGS and once you do, you can use code similar to this:

local myTable = { play = 1 } local snapshotFilename = "snapshot1" local data = json.encode( myTable ) local function gpgsSnapshotOpenForReadListener( event ) print( "snapshot open event:", json.prettify(event) ) if not event.isError then local data = event.snapshot.contents.read() native.showAlert('Snapshots', 'Reading was ' .. (event.isError and 'unsuccessful' or 'successful') .. ',', { 'OK'}) end end local function gpgsSnapshotAfterSaveListener( event ) native.showAlert('Snapshots', 'Saving was ' .. (event.isError and 'unsuccessful' or 'successful') .. '.', {'OK'}) end timer.performWithDelay(10000, function() print("Opening snapshot") gpgs.snapshots.open({ filename = snapshotFilename, listener = gpgsSnapshotOpenForReadListener }) end, 1) local function gpgsSnapshotOpenForSaveListener( event ) if not event.isError then event.snapshot.contents.write(data) -- Write new data as a JSON string into the snapshot gpgs.snapshots.save({ snapshot = event.snapshot, description = 'Save slot ' .. snapshotFilename, listener = gpgsSnapshotAfterSaveListener }) end end local function saveSnapShot() print("saving snapshhot") gpgs.snapshots.open({ -- Open the save slot filename = snapshotFilename, create = true, -- Create the snapshot if it's not found listener = gpgsSnapshotOpenForSaveListener }) end

after you’re logged in.

I don’t have iCloud code handy, but it’s similar, If your data isn’t too much, the key-value pair method is the easiest thing to do. You can use a simple string and store your JSON encoded string there. However, it’s recommended that you save each table entry as their own key-value pair so you can update small things instead of one big table. This will help keep multiple devices in better sync.

I understand … I’m sorry for ios and what I would rather not risk.

Anyway, I would have two questions about this yet

  1. I see that you’ve made an example with a given play = 1.

    Is there no way to save files that are currently saved in a “system.DocumentsDirectory”?

  1. Do I need to update this data manually?

I thought that google play and game center once logged in, manually make buckup of my data in system.DocumentsDirectory…

Hi Jake.  It seems that you are asking unrelated questions about something that may seem like it’s the same thing.

Let’s break this down into the various parts.

  1. Backups

iOS will automatically backup the files in system.DocumentsDirectory. They won’t be shared with other devices owned by the same iCloud account. This is used if you need to restore your device for some reason.  If you delete your app and reinstall it, I don’t believe you will be able to recover the saved files since you took the step to remove it yourself.  I believe Android has some backup facilities, but I’m not sure how they work. Regardless, these type of backups are not for sharing saved games between devices or saving checkpoints to resume from later.

  1. Shared data

Based on your original descriptions and videos, this is what it sounds like you’re customers are asking for. This is what I described above.  For iOS, saved/shared game data is iCloud based, but Apple uses different iCloud technology. The iCloud plugin supports simple key-value pairs, saved documents, and a full-fledged relational database for more complex data needs.  You could use the documents mode of the iCloud plugin to save your settings.json file and then other apps can be be granted access to get it and update it. However, this isn’t that great of a way to save game data that will be shared between the devices. Uploading and downloading files are a bit slower and you have to take the whole file, then open it and read it in your other app. It’s more management on your side.  The ideal way is to take each variable you want to save and write them as their own key.value pair.  You could do something like (untested code)

for key, value in pairs(yourSavedDataTable) do     iCloud.set( key, value ) end

Then reverse that to load it:

local yourSavedDataTable = {} yourSavedDataTable.score = iCloud.get( "score" ) yourSavedDataTable.currentLevel = iCloud.get( "currentLevel" ) etc.

Of course you have to include the iCloud plugin in your build.settings, and require it in the modules where you want to use it. And there are some entitlements that have to be setup in your developer profile’s App settings and then you will need to generate a new provisioning profile that has those entitlements in them.  (scarier than it sounds)

For GPGS, you’re going to use Snapshots which stores a string of data. The best way to make that is to json.encode() your saved data table, much like the loadsave.lua module does to write the settings to storage. This string is saved in your snapshot. You can load it in, json.decode() it back to a Lua table.  When I did this:

local myTable = { play = 1 }

I was just making up a sample table with a sample value in it. You would use your settings table instead of mine with whatever content you have in it.

Rob

Thanks a lot Rob.

Honestly I thought it was much simpler. But apparently implementing this is long and difficult.

However, you have centered the point. The main reason for asking here is to keep memorized player data. Even though they change phone …

When you say “change phone”, do you mean get a new phone and restore the new phone from backups? In that case iOS does that if the user backs up to iCloud or backs up to iTunes before getting their new phone. I don’t know how Android does this, but it’s similar.

If you say “change phone” as in “Let me play on one phone for 10 minutes then switch to a different phone and want to resume the game” that’s different and you have to do more.

Rob

Who asked you?

Do you have some screen shots for context?

Rob

I had provided my mail I received the feedback.

I have been asked for various things, and one of them was what I asked.

In almost every game, however, it is now possible. A button that lets you go to google play to save your data. And the same service is also available for iOS. This is also often used to have more profiles of the same game on a device.

Is it clear what I need? Or did I explain it badly? I’m not native speaker…

“I launched a beta of my game and they asked me to enter access”

Are you saying “they” are your customers? Or is Google asking you to do this? That’s what I’m trying to figure out. I’ve never seen Google ask for this.

But I think I understand a little better. You want to be able to save your current game/data, possibly in a way that people can switch devices and resume play where they left off. Is that the question?

If so, you should create a table in your game that holds all of the data you want to save: current level, score, coins collected, etc., every thing you need to resume the game at some point. In the game I’m making you can’t resume in the middle of the level, but I let you resume at the last level you started. 

The general workflow when the game starts is to:

  1. Look to see if your saved data exists. If so load it and populate your save data table.

  2. If it does not, create your save data table and populate it with starting values for the first level of your game.

  3. When you make a change to any of those values, update the table and save the table.

You only need to load the table when the app first starts up from having been edited. If it’s just suspended it should return you to where you were. 

Once you have all of this in a single table, you can use various techniques to save that data. If you are only concerned about local saves, you can use something like the loadsave module here: https://github.com/robmiracle/Simple-Table-Load-Save-Functions-for-Corona-SDK

If you want to do cloud saves, then you can, but it will require you to do different things for Android and iOS. On iOS you would use our iCloud plugin. See: https://docs.coronalabs.com/plugin/iCloud/index.html

For Android you will use the GPGS plugin and use snapshots. See: https://docs.coronalabs.com/plugin/gpgs/snapshots/index.html

Rob

Okay then I’ll explain it better.

Yes, my customers have asked me this.

I have no problem saving game data in the phone(local). I already use the technique you described to save the data.

I save several files in the path:

system.DocumentsDirectory

To this point everything is perfect.

What you have recommended with iCloud is more or less what I need… However I was specifically asked to use access to the 2 stores.

To explain this use a video on a famous game:

Andoid: https://www.youtube.com/watch?v=_jYx60T3rhA

iOS     : https://www.youtube.com/watch?v=phZ6A9BMnDE

I believe there is a simple way to get the data that I save locally and save them to the store. (Following the acess of the user)

I hope I was clear. I apologize if initially I did not explain it well

That’s what I shared with you. For GPGS it’s called Snapshots. You can save various data types to GPGS and load them back as needed.  You do have to be logged in to GPGS and once you do, you can use code similar to this:

local myTable = { play = 1 } local snapshotFilename = "snapshot1" local data = json.encode( myTable ) local function gpgsSnapshotOpenForReadListener( event ) print( "snapshot open event:", json.prettify(event) ) if not event.isError then local data = event.snapshot.contents.read() native.showAlert('Snapshots', 'Reading was ' .. (event.isError and 'unsuccessful' or 'successful') .. ',', { 'OK'}) end end local function gpgsSnapshotAfterSaveListener( event ) native.showAlert('Snapshots', 'Saving was ' .. (event.isError and 'unsuccessful' or 'successful') .. '.', {'OK'}) end timer.performWithDelay(10000, function() print("Opening snapshot") gpgs.snapshots.open({ filename = snapshotFilename, listener = gpgsSnapshotOpenForReadListener }) end, 1) local function gpgsSnapshotOpenForSaveListener( event ) if not event.isError then event.snapshot.contents.write(data) -- Write new data as a JSON string into the snapshot gpgs.snapshots.save({ snapshot = event.snapshot, description = 'Save slot ' .. snapshotFilename, listener = gpgsSnapshotAfterSaveListener }) end end local function saveSnapShot() print("saving snapshhot") gpgs.snapshots.open({ -- Open the save slot filename = snapshotFilename, create = true, -- Create the snapshot if it's not found listener = gpgsSnapshotOpenForSaveListener }) end

after you’re logged in.

I don’t have iCloud code handy, but it’s similar, If your data isn’t too much, the key-value pair method is the easiest thing to do. You can use a simple string and store your JSON encoded string there. However, it’s recommended that you save each table entry as their own key-value pair so you can update small things instead of one big table. This will help keep multiple devices in better sync.

I understand … I’m sorry for ios and what I would rather not risk.

Anyway, I would have two questions about this yet

  1. I see that you’ve made an example with a given play = 1.

    Is there no way to save files that are currently saved in a “system.DocumentsDirectory”?

  1. Do I need to update this data manually?

I thought that google play and game center once logged in, manually make buckup of my data in system.DocumentsDirectory…

Hi Jake.  It seems that you are asking unrelated questions about something that may seem like it’s the same thing.

Let’s break this down into the various parts.

  1. Backups

iOS will automatically backup the files in system.DocumentsDirectory. They won’t be shared with other devices owned by the same iCloud account. This is used if you need to restore your device for some reason.  If you delete your app and reinstall it, I don’t believe you will be able to recover the saved files since you took the step to remove it yourself.  I believe Android has some backup facilities, but I’m not sure how they work. Regardless, these type of backups are not for sharing saved games between devices or saving checkpoints to resume from later.

  1. Shared data

Based on your original descriptions and videos, this is what it sounds like you’re customers are asking for. This is what I described above.  For iOS, saved/shared game data is iCloud based, but Apple uses different iCloud technology. The iCloud plugin supports simple key-value pairs, saved documents, and a full-fledged relational database for more complex data needs.  You could use the documents mode of the iCloud plugin to save your settings.json file and then other apps can be be granted access to get it and update it. However, this isn’t that great of a way to save game data that will be shared between the devices. Uploading and downloading files are a bit slower and you have to take the whole file, then open it and read it in your other app. It’s more management on your side.  The ideal way is to take each variable you want to save and write them as their own key.value pair.  You could do something like (untested code)

for key, value in pairs(yourSavedDataTable) do     iCloud.set( key, value ) end

Then reverse that to load it:

local yourSavedDataTable = {} yourSavedDataTable.score = iCloud.get( "score" ) yourSavedDataTable.currentLevel = iCloud.get( "currentLevel" ) etc.

Of course you have to include the iCloud plugin in your build.settings, and require it in the modules where you want to use it. And there are some entitlements that have to be setup in your developer profile’s App settings and then you will need to generate a new provisioning profile that has those entitlements in them.  (scarier than it sounds)

For GPGS, you’re going to use Snapshots which stores a string of data. The best way to make that is to json.encode() your saved data table, much like the loadsave.lua module does to write the settings to storage. This string is saved in your snapshot. You can load it in, json.decode() it back to a Lua table.  When I did this:

local myTable = { play = 1 }

I was just making up a sample table with a sample value in it. You would use your settings table instead of mine with whatever content you have in it.

Rob

Thanks a lot Rob.

Honestly I thought it was much simpler. But apparently implementing this is long and difficult.

However, you have centered the point. The main reason for asking here is to keep memorized player data. Even though they change phone …

When you say “change phone”, do you mean get a new phone and restore the new phone from backups? In that case iOS does that if the user backs up to iCloud or backs up to iTunes before getting their new phone. I don’t know how Android does this, but it’s similar.

If you say “change phone” as in “Let me play on one phone for 10 minutes then switch to a different phone and want to resume the game” that’s different and you have to do more.

Rob