Hey everyone. I’m finding a save issue in my (getting fairly large) game. I have 27 values saving in a table with 5 sub-tables. However after saving and reloading occasionally one of the sub-tables becomes corrupted. I’ve changed this code multiple times trying to fix it and I’m almost certain there’s some bug in the save code. I’ve only had it happen so far on Windows but it probably occurs on Android too (but haven’t confirmed.) Does anyone know where in the Defold code the save logic is so I can check over it? I’d like to understand how it works and make sure there isn’t some sub-table issue.
EDIT: Otherwise is there a way to disable LuaJIT for windows/android testing? I’ve been having strange irregularities in the logic which I can’t trace to the code. Granted, my project is quite large so it might be something I just can’t track down.
Are you getting errors related to table size being too big / too small? You could try serializing your tables to something else and then saving it directly / loading and converting it back to tables.
A common error could look like this
buffer (3554 bytes) too small for table, exceeded at key for element
I might try this. I don’t see any error, but the data loads with one wrong integer value for one offset in the table. It’s always the same table that it happens it which makes me think it has to be related to my code, but I’ve searched every usage of the table in my project and see no issues anywhere. Perhaps I’ll try serializing this one table to avoid the issue. I see the engine has JSON decoding but no encoding seemingly. If only that was supported the issue could be avoided by saving the game w/ both formats (one as a backup format) that the player could revert to if an issue occurred.
But for serious game data you should look into binary encoding. It can save you lots of disk space. I’ve not done this with Defold but others may have something handy already.
Thank you, the table that is having the issue isn’t too large yet (only about ~36 integer values at various nested depths.) So JSON would probably be reliable for this. I looked at the read code in the code you posted and I’m seeing it uses fread which from what I am seeing online is not thread safe. Do you know if the load operation in Defold happens synchronously or could it happen within a thread?
Hopefully he knows. I’m seeing on Stackoverflow: https://stackoverflow.com/questions/22366776/is-reading-and-writing-to-the-same-file-thread-safe that one should use flockfile() and funlockfile() if it’s used concurrently. So maybe that’s an issue. My game saves immediately after loading since the level initialization logic in my game calls save game to save the player’s position in the world. I’ll probably just create a global to disable the first save to avoid some race condition if it’s concurrently saving and loading from the same data.
Oh, and since you mention multiple sub tables couldn’t it be a problem that you accidentally use the same sub table in multiple places instead of deep copies or something like that?
No, there’s no easy way to disable it. You can ofc start a HTML5 build?
However, I wouldn’t start looking at discrepancies between Lua and LuaJIT. I’d start looking at my own code first.
Do you know if the load operation in Defold happens synchronously or could it happen within a thread?
The sys.save() and sys.load() are synchronous on the Lua thread.
Have you asserted that your data is correct before saving?
Following the comment from Björn, you can print the tables with ´pprint(t)` before saving. That way you’ll see the pointers for each table in the hierarchy, perhaps there’s a clue in there.
I disabled saving immediately after the load. I’ll see if this issue occurs again. Unfortunately it’s so infrequent that I can’t pin down what’s causing it.
EDIT: Last time I checked the data was saved correctly but after loading it loaded bad data and then immediately saved over the good data with the old code.