• We are currently performing site maintenance, parts of civfanatics are currently offline, but will come back online in the coming days (this includes any time you see the message "account suspended"). For more updates please see here.

Questions about loading and saving mod data

General Tso

Panzer General
Joined
Oct 12, 2007
Messages
1,548
Location
U. S. of A.
I'm working on a mod for the advanced setup screen. I plan on adding many option that will need to be saved for the next time the user starts a game with the advance setup screen. Since I want the data to be saved independent to saved games it looks like Modding.OpenUserData() is the way to go. I tried it using the SetValue() function and it works well. Unfortunately saving each piece of data separately is very slow - it causes a noticeable delay when doing so. I could convert my tables that need saved to a few big strings and save them but this is still kind of slow (not to mention a pain in the butt). I'm hoping there is a better way. Does anybody have any ideas?

I've noticed that some mods appear to access the database directly using .Query. Can I used this method the both load and save data? Would it be faster than the method mentioned above. If so how do I do it. Please be gentle - I know nothing about SQL. :confused:

Sorry for all of the questions - I tried searching for answers but my lack of knowledge on databases just left me confused.
 
Since I want the data to be saved independent to saved games it looks like Modding.OpenUserData() is the way to go.
Correct

I've noticed that some mods appear to access the database directly using .Query. Can I used this method the both load and save data?
Yes

Would it be faster than the method mentioned above.
Yes, every SetValue()/GetValue() call executes in it's own transaction, reading all parameters from a single row of a table would be just one transaction.


If so how do I do it.
As gentle as possible, but you'll still need to understand some SQL!

Code:
-- Connect to the database, put this near the top of the lua file
local userData = Modding.OpenUserData("CoopWarData", 1)

Code:
-- Create the database table if need be, the "IF NOT EXISTS" stops an error on second and subsequent calls
local sQuery = "CREATE TABLE IF NOT EXISTS UIDiary_CoopWar(Turn INTEGER NOT NULL, Player INTEGER NOT NULL, WithPlayer INTEGER NOT NULL, AgainstPlayer INTEGER NOT NULL)"
for _ in userData.Query(sQuery) do end  -- note the use of an empty loop to execute the statement!

Code:
-- Put some data into the table
local sQuery = string.format("INSERT INTO UIDiary_CoopWar(Turn, Player, WithPlayer, AgainstPlayer) VALUES(%d, %d, %d, %d)", iTurn, iPlayer, iPlayerWith, iPlayerAgainst)
for _ in userData.Query(sQuery) do end  -- again note the use of the empty loop!

Code:
-- Get the data back
local sQuery = string.format("SELECT Turn, WithPlayer, AgainstPlayer FROM UIDiary_CoopWar WHERE Player = %d AND Turn >= %d", pPlayer:GetID(), Game.GetGameTurn())
for row in userData.Query(sQuery) do
  local iTurns = row.Turn - iGameTurn

  if (iTurns > 0) then
    local sCivWith = Players[row.WithPlayer]:GetCivilizationShortDescriptionKey()
    local sCivAgainst = Players[row.AgainstPlayer]:GetCivilizationShortDescriptionKey()
	
	-- Do something useful here
  end
end

The only real "gotcha" is the query doesn't actually execute until you attempt to iterate over the results set - so even if the query doesn't return any rows you MUST still iterate over the empty set.

The following WILL NOT WORK!!!
Code:
-- Put some data into the table
local sQuery = string.format("INSERT INTO UIDiary_CoopWar(Turn, Player, WithPlayer, AgainstPlayer) VALUES(%d, %d, %d, %d)", iTurn, iPlayer, iPlayerWith, iPlayerAgainst)
userData.Query(sQuery) -- [COLOR="red"]WRONG!!!![/COLOR]

HTH

W
 
Thank you for the excellent reply whoward69. I'm off to try my new found skills... :)
 
Back
Top Bottom