Basically you're responsible for putting together a table that contains all the data you need for your game. So, for example, your table might contain a matrix for the player's last position/rotation in the world, a number that indicates the last level the player was on, and a table for each level in the game that contains a boolean value for each inventory item that the player can collect, to indicate whether it's been found.
Once you have your data ready, you call
stingray.SaveSystem.auto_save("filename", table)
to record your table to a file. As mentioned earlier, this gets saved to the location you set in the settings.ini file.
When you need to restore a game from saved data, you call
token = stingray.SaveSystem.auto_load("filename")
to get the data back from the file. This function returns a "token" ID that identifies your request.
This call is *asynchronous*, which means that it may take several frames to finish loading. So, after you call auto_load, you have to call
local progress_data = stingray.SaveSystem.progress(token)
and pass it your loading token. This function returns a table that tells you when the saved data is fully loaded. When progress.done is true, then you can get back the table you originally saved in your call to auto_save from progress.data.
Here's some code from an example project that shows it in practice.
First, the table is set up in SaveManager.data.
Every time the player completes a level, SaveManager.needToSave is set to true, and the next frame update the SaveManager.save_file function gets called, which calls SaveSystem.auto_save().
Every time a new game is started and the save system is initialized, it tries to load the same file in SaveManager.init. It saves the token in SaveManager.token. Then, each update, SaveManager.onProgress calls SaveSystem.progress() to check how the load is progressing. If the request is finished, and it has data, then it copies that data back to SaveManager.data.
Project.SaveManager = Project.SaveManager or {}
local SaveSystem = stingray.SaveSystem
local SaveManager = Project.SaveManager
SaveManager.data = SaveManager.data or {}
SaveManager.initDone = false
SaveManager.isFirst = true
SaveManager.needToSave = false
function SaveManager.enabled()
return SaveSystem.exists()
end
function SaveManager.init()
if not SaveManager.initDone then
SaveManager.create_empty_data()
if SaveManager.enabled() then
print("Save Manager is ENABLED")
SaveManager.load_file()
else
print("Save Manager is DISABLED")
end
SaveManager.initDone = true
end
end
function SaveManager.create_empty_data()
for nameCount = 1, 20 do
SaveManager.data["Level_"..nameCount] = {
["big_star_taken"] = false,
["stars"] = 0,
["locked"] = true
}
end
SaveManager.data["Level_1"]["locked"] = false
end
function SaveManager.is_level_locked(levelNumber)
if not SaveManager.enabled() then return false end
return SaveManager.data["Level_"..levelNumber]["locked"]
end
function SaveManager.is_star_collected(levelNumber)
if not SaveManager.enabled() then return false end
return SaveManager.data["Level_"..levelNumber]["big_star_taken"]
end
function SaveManager.get_stars_collected(levelNumber)
if not SaveManager.enabled() then return 0 end
return SaveManager.data["Level_"..levelNumber]["stars"]
end
function SaveManager.load_file()
if not SaveManager.enabled() then return end
SaveManager.token = SaveSystem.auto_load("data_file")
end
function SaveManager.save_file()
if not SaveManager.enabled() then return end
SaveManager.token = SaveSystem.auto_save("data_file", SaveManager.data)
end
function SaveManager.onProgress()
if not SaveManager.enabled() then return end
-- if stingray.Keyboard.pressed(stingray.Keyboard.button_id("a")) then
-- SaveManager.data["level_1"]["stars"] = SaveManager.data["level_1"]["stars"] + 1
-- SaveManager.save_file()
-- end
-- Save the file when invoked from other thread
if (SaveManager.needToSave) then
SaveManager.needToSave = false
SaveManager.save_file()
return
end
if (SaveManager.token) then
local progress = SaveSystem.progress(SaveManager.token)
if (progress and progress.done) then
--print ("save - load done !")
if (progress.error) then
if (progress.error == "STINGRAY_SAVEDATA_ERROR_MISSING") then
-- File is missing - need to create new empty file and save it !
SaveManager.create_empty_data()
SaveSystem.close(SaveManager.token)
SaveManager.token = nil
SaveManager.save_file()
-- SaveManager.update_menu()
print ("save - load token closed")
end
else
print ("File is Loaded OK...")
-- Reading... only on loading
if (progress.data) then
SaveManager.data = progress.data
-- SaveManager.update_menu()
end
print ("Stars "..SaveManager.get_stars_collected(1))
SaveSystem.close(SaveManager.token)
SaveManager.token = nil
end
end
end
end
function SaveManager.shutdown()
if not SaveManager.enabled() then return end
if (SaveManager.token) then
print ("Finallizing...")
SaveSystem.close(SaveManager.token)
end
end
function SaveManager.update_menu()
if SimpleProject.level_name ~= "content/levels/Menu" or next(SaveManager.data) == nil then
return false
end
local nora = stingray.World.unit_by_name(SimpleProject.world, "Character_Main2")
if SaveManager.isFirst then
stingray.Unit.flow_event(nora,"initPositionInMenu")
SaveManager.isFirst = false
else
stingray.Unit.flow_event(nora,"positionInMenu")
end
for i = 1, 20 do
local level_unit = stingray.World.unit_by_name(SimpleProject.world, "Level_" .. i)
local locked = SaveManager.is_level_locked(i)
local starCollected = SaveManager.is_star_collected(i)
stingray.Unit.set_mesh_visibility(level_unit, "Lock", locked)
stingray.Unit.set_mesh_visibility(level_unit, "Star_00", not locked)
stingray.Unit.set_data(level_unit,"starCollected",starCollected)
stingray.Unit.flow_event(level_unit,"updateStar");
local stars = SaveManager.get_stars_collected(i)
for j = 1, SaveManager.get_stars_collected(i) do
stingray.Unit.set_mesh_visibility(level_unit, "Star_0" .. j, not locked)
end
for j = stars+1, 5 do
stingray.Unit.set_mesh_visibility(level_unit, "Star_0" .. j, false)
end
end
return true
end
-- level is the current level
function SaveManager.on_level_completed(level, numStars, hasBigStar)
if (level < 21) then
SaveManager.data["Level_" .. level+1]["locked"] = false
end
SaveManager.data["Level_" .. level]["stars"] = numStars
SaveManager.data["Level_" .. level]["big_star_taken"] = hasBigStar
SaveManager.needToSave = true
end
function SaveManager.get_max_levels_passed()
if not SaveManager.enabled() then return 20 end
for i = 1, 20 do
if (SaveManager.data["Level_"..i]["locked"] == true) then
return i-1
end
end
return 20
end
return SaveManager