Saving Lua Tables

qqqbbb

Prince
Joined
Sep 25, 2010
Messages
530
Best way to save mod data is using "Modding.OpenSaveData().SetValue(key,value)" method. But it does not allow saving tables. So, we have to convert a table we want to save to a string. This is called table serialization. Here is a simple table serialization code:
Code:
local savedData = Modding.OpenSaveData()

function SaveLuaTable(sKey, tTable)
	local s = ''
	for k, v in pairs(tTable) do
		-- print('SaveLuaTable ',k,v)
		local sDataType = type(v)
		if sDataType == 'table' then
			SaveLuaTable(sKey..k, v)
			s = s..sDataType..':'..k..':'..' '..';'
			-- print('s SaveLuaTable table',sKey..k)
		elseif sDataType == 'boolean' then
			s = s..sDataType..':'..k..':'..tostring(v)..';'
		else
			s = s..sDataType..':'..k..':'..v..';'
		end
	end
	savedData.SetValue(sKey, s)
	-- print('s SaveLuaTable',sKey, s)
end


function LoadLuaTable(sKey, tTable)
	local s = savedData.GetValue(sKey)
	if s then
		for ss in string.gmatch(s, '([^;]+)') do
			local sDataType, k, v = ss:match('([^:]+):([^:]+):([^:]+)')
			-- print('LoadLuaTable '..sDataType,k,v)
			if not string.match(k, '%D+') then -- only digits found
				k = tonumber(k)
			end
			if sDataType == 'boolean' then
				if v == 'true' then
					tTable[k] = true
				elseif v == 'false' then
					tTable[k] = false
				end
			elseif sDataType == 'number' then
				tTable[k] = tonumber(v)
			elseif sDataType == 'string' then
				tTable[k] = v
			elseif sDataType == 'table' then
				local tTempTable = {}
				LoadLuaTable(sKey..k, tTempTable)
				tTable[k] = tTempTable
			end
		end
	end
end
This code has followong limitations:
1. Your table keys can only be numbers or strings.
2. Your table values can only be numbers, strings, booleans or tables.
3. Your strings can not contain colon or semicolon characters.
4. Key that you use to save or load a table can only be a string.

To use the code either copy it to your lua file or create a new one named "SaveLoadLuaTables.lua" (with VFS property set to true) and add to your lua file line "include('SaveLoadLuaTables.lua')".

To save a table run "SaveLuaTable(key, tTable)". First argument is a string to identify your saved table. Second argument is a table you want to save.
To load a table run "LoadLuaTable(key, tTable)". Don't forget to create an empty table ("tTable = {}") before trying to load it.
 
Both OpenSaveData() and OpenUserData() support the Query() method, so you have full access to the underlying SQLite database, eg

Code:
local SpyMapDB = Modding.OpenSaveData()

function SpyMapDbUpdate(...)
  for _ in SpyMapDB.Query(sQuery, ...) do end
end

SpyMapDbUpdate("CREATE TABLE IF NOT EXISTS SpyMap_Agent('Player' integer NOT NULL, 'Agent' integer NOT NULL, 'IsMapping' integer DEFAULT 0, 'IsPausing' integer DEFAULT 0, 'CityX' integer DEFAULT -1, 'CityY' integer DEFAULT -1, 'RiskFactor' integer DEFAULT 100, 'MapType' text DEFAULT 'sweep', 'MapRadius' integer DEFAULT 4, 'MapSector' integer DEFAULT 1, 'MapDirection' integer DEFAULT 0, 'AnalysePlotX' integer DEFAULT -1, 'AnalysePlotY' integer DEFAULT -1, 'AnalysePlotCostTimes100' integer DEFAULT 0, 'AnalyseTimeTimes100' integer DEFAULT 0, 'ReportReset' integer DEFAULT 0, 'ReportTurns' integer DEFAULT 0, PRIMARY KEY (Player, Agent))")

SpyMapDbUpdate("INSERT INTO SpyMap_Agent(Player, Agent) VALUES(?, ?)", iPlayer, iAgent)

SpyMapDbUpdate("UPDATE SpyMap_Agent SET RiskFactor=? WHERE Player=? AND Agent=?", iRiskFactor, iPlayer, iAgent)
 
Back
Top Bottom