ss.data is a table that stores information persistently between runs of the game, in the same way as LunaLua's SaveData. Numbers, strings, booleans and nested tables kept in it are written to the mod's save.lua file and read back when the mod loads, so a best lap, a settings table or a run counter survives a restart without any file handling in the mod.

Static members#

These elements are static to the class itself and can be accessed like so:

ss.data.runs = (ss.data.runs or 0) + 1

Static functions#

FunctionReturn ValuesDescription
ss.save_data() boolean saved Writes ss.data to the mod's save file immediately. Returns false, with a line in the log, when the table cannot be saved.
ss.reset_data() nil Empties ss.data and removes the mod's save file.

Static fields#

TypeFieldRead-only?Description
table ss.data No The persistent table. It can be replaced or assigned into; both are saved.
string ss.data_path Yes The path of the file ss.data is written to.

When it is saved#

The table is written when ss.save_data() is called, at the end of every race, and every 60 seconds. A crash between two automatic saves loses whatever was changed after the last one, so a value that matters is best saved explicitly, as the example does for a best lap.

What is saved#

Numbers, strings, booleans and tables of them, nested to any depth. Functions and userdata (a live object, for example) are skipped, and a cyclic table makes ss.save_data() return false with a line in the log. A live object's snapshot, or a vector's :table(), can be kept in place of the object itself.

The file#

The file is Mods\<mod>\save.lua for a mod folder and Mods\<mod>.zip.save.lua for a zipped mod, next to the archive, as the archive itself is never written to. It is Lua, of the form return { ... }, with its keys sorted, so it diffs cleanly and can be edited by hand. A file that fails to parse is reported in the log and left alone, and ss.data starts empty for that run.

Mods\MyMod\save.lua
return {
	best = 76.034,
	runs = 12,
	settings = {
		enabled = true,
		laps = 3,
	},
}

Example#

-- Keeps the local player's best lap across runs.
ss.on("lap_time", function(ev)
	if ev.is_local and (ss.data.best == nil or ev.time < ss.data.best) then
		ss.data.best = ev.time
		ss.save_data()
	end
end)