Problem saving myData with JSON.

Hi All,

I’m trying to use JSON to save and load the levels settings table in myData.lua file

I try to save the table every time I update it when the level is completed

And to load the table when I create the level selection scene.

I copy to my main directory the file loadsave.lua from the tutorial: Saving and Loading Lua Tables with JSON.

I added to all the relevant files the line local loadsave = require( “loadsave” )

levelDate is the name of the lua file that holds table M

To save the table I use the below line:

levelData.M.settings = loadsave.loadTable( “settings.json”, system.DocumentsDirectory )

I also tried to use it like this levelData.M.settings = loadsave.loadTable( “settings.json” )

To load the table I use the below line:

 loadsave.saveTable( levelData.M.settings, “settings.json”, system.DocumentsDirectory )

When running the simulator I receive the below error:

“attempt to index field ‘M’ (a nil value)”

What am I missing?

Regards,

Guy

Hi guys

 

After reorganization of my code and some bugs fixing I return to the subject which I cannot save/load the scores of my levels after “Cold” start.

 

I was able to clear the error I mention before “attempt to index field ‘M’ (a nil value)” by saving/loading the entire table M

For example: loadsave.saveTable( levelData.M, “settings.json”, system.DocumentsDirectory )

 

But when I relaunch the simulator I see only the values of the default table.

 

Any suggestion?

 

Regards,

Guy

are you trying to load score and highScore?

levelData. M. settings = loadsave.loadTable( “settings.json”, system.DocumentsDirectory )

Leave the M. off and try it. Assuming that levelData is a table already. Then you have levelData.settings which should work.

The M. is a way of defining a module inside the file being required. It’s short for “Module”. You can really name the table inside the module anything you want, but M is the standard most people use.

But it’s M that gets returned by the required, so you don’t need it in the code where you required it.

Rob

Hi

SonicX278, I’m trying to save for each level the highScore and the number of “stars”

Rob, Removing the M still give the same result.

I found the setting.json file in the Sandbox of the corona simulator with the default table, I don’t see the new score/”stars”

Here is my function to save the data to the table, in the function I’m checking if the player receive more stares or higher score

function updateLevedata (levelBallScore) – levelBallScore is the number of stars the player receive in the current level

                local levelnum = tonumber(levelData.settings.currentLevel)

                if (levelBallScore >= levelData.settings.levels[levelnum].stars) then

                                levelData.settings.levels[levelnum].stars = levelBallScore

                                if (scoreNum > levelData.settings.levels[levelnum].score) then

                                                levelData.settings.levels[levelnum].score = scoreNum

                                end

                                loadsave.saveTable( levelData.settings, “settings.json” )

                end

When I’m moving between levels (in the level select screen) I can see the new score/starts that I saved in my levelData table

I also can see older settings.json files in sub-directories in the Sandbox…… Is it expected?

Regards,

Guy

Any ideas?

Guy

This condition has to be true:

if (levelBallScore >= levelData.settings.levels[levelnum].stars) then

before you can get to your save call. I would put in some print statements and check the values you are comparing. There should only be one settings.json file in your system.Documents directory and it should be the last one you saved last.

Rob

Thank you Rob

I did put same debug prints to verify that I getting into the function as expected

I also remove the saveTable call from the function to the scene:show of the  complete level scene, I also change the default values I have in the levelData file to make sure I see the changes in the settings.json file in the sandBox.

Still when I relaunch the simulator I see only the default values of the table in the levelData.

I also verify that I have only one setting.json file in the relevant game directory

The strange thing is that I can see the setting.json file in the sendBox with the default values.

After I complete the level I can see the new score in the level select menu but I don’t see it in the setting.json file…

The only place I update the table is in the complete level scene

I don’t know what can I do, can you point me to a different method to save the game (using a table for multiple levels)?

Regards,

Guy

Are you doing anything with loading/saving the table in your main.lua?

Rob,

I forgot the main.lua file, I have two lines of code it this file and one of them is:

"loadsave.saveTable( levelData.settings, “settings.json”

I comment out this line and I can save and reload the new table with the new score.

 

Thank you Rob

:slight_smile:

 

 

Now I need to understand why this line cause the problems. :wacko:

 

 

Regards,

Guy

It really helps to copy and paste text. The code above has an error. But if that’s in your main.lua and perhaps just above it somewhere you did:

levelData.settings = {}

followed by:

loadsave.saveTable( levelData.settings, "settings.json" )

then you are blowing away you’re previous settings file. Normally what I do is in main.lua:

levelData.settings = loadsave.loadTable( "settings.json" ) if levelData.settings == nil then  -- did not load the settings file, assume first -- time running app or the user killed the app and restarting cold.     levelData.settings = {}     --     -- Set your default values here     --     loadsave.saveTable( levelData.settings, "settings.json" ) end

Think about it this way. You only ever need to load the table once and that’s when the app starts cold. If it was just in the background and the user switched back to it, the code in main.lua doesn’t run again, the app is still running, it was just backgrounded. Your previous settings were still in memory.  If your user kills the app, then the next time they run it, it will need to resume with the last settings, so you have to read the table.

Now every time you change that table and the change is reasonably important, I would go ahead and call the loadsave.saveTable() function. It’s not that expensive of an operation. I wouldn’t delay until the user backgrounds the app to save. A force quit won’t trigger the suspended event. 

Rob

Hi Rob,

Thank you for your detailed answer

In your code you mention to insert the default values in the main.lua file

levelData.settings = loadsave.loadTable( “settings.json” )
if levelData.settings == nil then  – did not load the settings file, assume first
    –                                time running app or the user killed the app and restarting cold.
    levelData.settings = {}
    –
    – Set your default values here
    –
    loadsave.saveTable( levelData.settings, “settings.json” )
end

I have the default values in a table in the levelData file, do I need to link/copy it to the main file?

Can I hold the table in two files?

Here is an example of my table in levelData file

local M = {}

M.maxLevels = 50

M.settings = {}

M.settings.currentLevel = 1

M.settings.unlockedLevels = 4

M.settings.soundOn = true

M.settings.musicOn = true

M.settings.levels = {}

M.settings.levels[1] = {}

M.settings.levels[1].stars = 1

M.settings.levels[1].score = 1000

M.settings.levels[1].delay = 3000

M.settings.levels[1].balls = {}

M.settings.levels[1].balls.red    = 5

M.settings.levels[1].balls.blue   = 4

M.settings.levels[1].balls.green  = 4

M.settings.levels[1].balls.yellow = 4

Regards,

Guy

Hi Rob,

Its working…….

THANK YOU

levelData.settings = loadsave.loadTable( “settings.json” )

if levelData.settings == nil then  – did not load the settings file, assume first

    –                                time running app or the user killed the app and restarting cold.

    levelData.settings = {}

    –

    – Set your default values here

    –

levelData.settings.currentLevel = 1

levelData.settings.unlockedLevels = 1

levelData.settings.soundOn = true

levelData.settings.musicOn = true

levelData.settings.levels = {}

levelData.settings.levels[1] = {}

levelData.settings.levels[1].stars = 1

levelData.settings.levels[1].score = 1000

levelData.settings.levels[1].delay = 3000

levelData.settings.levels[1].balls = {}

levelData.settings.levels[1].balls.red    = 4

levelData.settings.levels[1].balls.blue   = 4

levelData.settings.levels[1].balls.green  = 4

levelData.settings.levels[1].balls.yellow = 4

    loadsave.saveTable( levelData.settings, “settings.json” )

end

Regards,

Guy

Hi Rob,

 

Its seems that my saving code still not working as expected.

New values for level completed are not saved as expected

 

This is what I have for now.

 

In the main.lua I have some default values in case game runs for the first time (values are only for level1 and general settings )

I have a leveldata.lua file that holds the table of all the levels default settings (including level1).

After player complete the level with higher score I’m saving the table.

In the sandbox I see the new level1 score but I don’t see all the levels settings I have in leveldata.lua table.

 

I can delete the leveldata.lua file and hold the table in my main file but before I do that i want to know if my current code setup can work.

 

 

Regards,

Guy

Hi guys

 

After reorganization of my code and some bugs fixing I return to the subject which I cannot save/load the scores of my levels after “Cold” start.

 

I was able to clear the error I mention before “attempt to index field ‘M’ (a nil value)” by saving/loading the entire table M

For example: loadsave.saveTable( levelData.M, “settings.json”, system.DocumentsDirectory )

 

But when I relaunch the simulator I see only the values of the default table.

 

Any suggestion?

 

Regards,

Guy

are you trying to load score and highScore?

levelData. M. settings = loadsave.loadTable( “settings.json”, system.DocumentsDirectory )

Leave the M. off and try it. Assuming that levelData is a table already. Then you have levelData.settings which should work.

The M. is a way of defining a module inside the file being required. It’s short for “Module”. You can really name the table inside the module anything you want, but M is the standard most people use.

But it’s M that gets returned by the required, so you don’t need it in the code where you required it.

Rob

Hi

SonicX278, I’m trying to save for each level the highScore and the number of “stars”

Rob, Removing the M still give the same result.

I found the setting.json file in the Sandbox of the corona simulator with the default table, I don’t see the new score/”stars”

Here is my function to save the data to the table, in the function I’m checking if the player receive more stares or higher score

function updateLevedata (levelBallScore) – levelBallScore is the number of stars the player receive in the current level

                local levelnum = tonumber(levelData.settings.currentLevel)

                if (levelBallScore >= levelData.settings.levels[levelnum].stars) then

                                levelData.settings.levels[levelnum].stars = levelBallScore

                                if (scoreNum > levelData.settings.levels[levelnum].score) then

                                                levelData.settings.levels[levelnum].score = scoreNum

                                end

                                loadsave.saveTable( levelData.settings, “settings.json” )

                end

When I’m moving between levels (in the level select screen) I can see the new score/starts that I saved in my levelData table

I also can see older settings.json files in sub-directories in the Sandbox…… Is it expected?

Regards,

Guy

Any ideas?

Guy

This condition has to be true:

if (levelBallScore >= levelData.settings.levels[levelnum].stars) then

before you can get to your save call. I would put in some print statements and check the values you are comparing. There should only be one settings.json file in your system.Documents directory and it should be the last one you saved last.

Rob