Thread Tools Display Modes
03/02/14, 07:15 AM   #1
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
Problem Traversing the Saved Variables Table

Okay,

I have set up my Saved Variables table as follows:

Lua Code:
  1. local function InitSavedVariables(...)
  2.     SVData = ZO_SavedVars:NewAccountWide(addonSV, 1, "Data", SVDefault)
  3.     SVDataIndex = 1
  4. end

It then gets written to as follows:

Lua Code:
  1. SVData = SVData or {}
  2. SVData[zone] = SVData[zone] or {}
  3. SVData[zone][name] = SVData[zone][name] or {}
  4. SVDataIndex = #SVData[zone][name] + 1
  5. SVData[zone][name][SVDataIndex] = SVData[zone][name][SVDataIndex] or {}
  6. SVData[zone][name][SVDataIndex]["Action"] = action
  7. SVData[zone][name][SVDataIndex]["X"] = xPos
  8. SVData[zone][name][SVDataIndex]["Y"] = yPos
  9. SVData[zone][name][SVDataIndex]["Date"] = dateValue
  10. SVData[zone][name][SVDataIndex]["Time"] = timeValue

But when I try and traverse the table as follows:
Lua Code:
  1. local function RecurseSavedVariables(...)
  2.   -- Zone
  3.   for i,v in pairs(SVData) do
  4.     ChatMsg:AddMessage(string.format("(i,v) - %s : %s (%s)",tostring(i),tostring(v),type(v)))
  5.     if ( type(v) == "table" ) then
  6.       -- Name
  7.       for i2,v2 in pairs(v) do
  8.         ChatMsg:AddMessage(string.format("(i2,v2) - %s : %s (%s)",tostring(i2),tostring(v2),type(v2)))
  9.         if (type(v2) == "table") then
  10.           -- Values
  11.           for i3,v3 in pairs(v2) do
  12.             ChatMsg:AddMessage(string.format("(i3,v3) - %s : %s (%s)",tostring(i3),tostring(v3),type(v3)))
  13.           end
  14.         end
  15.       end
  16.     end
  17.   end
  18. end

It seems to think it has the following data in there:

GetInterfaceForCharacter : function : xxxxxxxx : (function)
default : table : xxxxxxxx : (table)

and despite having a table in there it doesn't traverse it further as expected, to see what else is hiding there.

Is there a special way to traverse the Saved Variables table in ESO ?
  Reply With Quote
03/02/14, 01:50 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 648
I have written down that the first parameter passed to your function should be a string. So... "addonSV"
  Reply With Quote
03/02/14, 02:29 PM   #3
Errc
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 30
Originally Posted by Seerah View Post
I have written down that the first parameter passed to your function should be a string. So... "addonSV"
addonSV is likely just a variable for whatever they named SV...

When your saved variables gets created it isn't blank. It stores the default values in a default table and GetInterfaceForCharacter is just a function there is in there. The default table is the same as SVDefault value, not sure what GetInterfaceForCharacter does, but it is in there all the same.

I suggest using Zgoo to examine your saved variables. You can see exactly how it is laid out and see how it reacts when you change values in it.
  Reply With Quote
03/02/14, 02:47 PM   #4
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
Originally Posted by Errc View Post
addonSV is likely just a variable for whatever they named SV...

When your saved variables gets created it isn't blank. It stores the default values in a default table and GetInterfaceForCharacter is just a function there is in there. The default table is the same as SVDefault value, not sure what GetInterfaceForCharacter does, but it is in there all the same.

I suggest using Zgoo to examine your saved variables. You can see exactly how it is laid out and see how it reacts when you change values in it.
But the question is why isn't it traversing it properly. Other tables work fine, just the saved variables one is messing up to the point of putting a stumbling block on me writing any addons that would need to access their respective tables.

I guess it's confusing me why SVData is linked to the Data part of the table for writing but not for reading.

The data is stored in the file as follows:

["Default"]
["@ACCOUNT"]
["$AccountWide"]
["Data"]
... data added by addon such as ..
["Khenarthi's Roost"]
["Aspect Rune"]
[1]
xPos = ...
yPos = ...
zone = ...
etc

when I use

for index,value in pairs(SVData) do
CHAT_SYSTEM:AddMessage(index,value,type(value))
end

I am expecting the first element to be "Khenarthi's Roost", xxxxxx, table telling me to traverse down a level to receive the second as "Aspect Rune",xxxxx,table, with the third as "1",xxxx,table, and the fourth displaying the first set of actual values.

However, if I say want to look for a specific item such as :

local zoneData = SVData["Khanarthi's Roost"]
local itemData = zoneData["Aspect Rune"]

CHAT_SYSTEM:AddMessage(itemData[1].xPos,itemData[1].yPos) would display fine ( formatting aside that is )
  Reply With Quote
03/02/14, 03:06 PM   #5
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
Looking at Esoheads Saved Variable table it looks like they do things differently so will try and do something similar with my addons.


Edit: Well after a lot of trial and error I finally almost had to copy what Esohead did and then adjust it to reflect my table contents.

Ended up changing the layout of the Saved Variables File and spec
Lua Code:
  1. local function InitSavedVariables(...)
  2.     SVData = {
  3.         ["History"] = ZO_SavedVars:NewAccountWide("XrysGatherer_SavedVariables", 1, "History", SVDefault)
  4.     }
  5.     SVDataIndex = 1
  6. end

And using the way Esohead traversed through the table as a guide the following works flawlessly.
Lua Code:
  1. ChatMsg:AddMessage("Traversing Harvest History")
  2.     for history,sv in pairs(SVData) do
  3.         ChatMsg:AddMessage(history)
  4.         if history == "History" then
  5.             for zone, t1 in pairs(SVData[history]) do
  6.                 for item, t2 in pairs(SVData[history][zone]) do
  7.                     for index, t3 in pairs(SVData[history][zone][item]) do
  8.                         local data = SVData[history][zone][item][index]
  9.                         ChatMsg:AddMessage(string.format("%d: %s %s in %s at %0.3f,%0.3f",index,item,tostring(data["Action"]),zone,data["X"],data["Y"]))
  10.                     end
  11.                 end
  12.             end
  13.         end
  14.     end

Last edited by Xrystal : 03/02/14 at 04:12 PM.
  Reply With Quote
03/02/14, 04:36 PM   #6
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
Okay, scratch the last reply.

It only works that way if I log in with an EMPTY!!!! Saved Variables table. Which totally defeats the point.


If I log in with an empty table that games session will correctly traverse the table ( maybe without the need for adding the history header table but I am not spending another half hour changing it back now ) but the moment I tell it not to clear the table out the old traverse problem returns.

By the way, what the heck is that version value for ? Should I set that to another value ?

Can some bright spark see what the heck I am doing wrong here or is it a bug in the SavedVariables table?

edit: As you can see this is annoying me to no end as I have wasted my beta weekend writing this addon and haven't been able to finish it because of this problem.

Here is my code in its entirety barring the Update routine being called from the XML as per the norm.
Lua Code:
  1. -- Values used often so created variables for them
  2. local addonName = "XrysGatherer"
  3. local addonVersion = "0.0.1"
  4. local addonSV = addonName.."_SavedVariables"
  5.  
  6. -- References to System and Manager objects
  7. local ChatMsg = CHAT_SYSTEM
  8. local EventMgr = EVENT_MANAGER
  9.  
  10. -- References to the Saved Variables Data
  11. local SVDefault = {}
  12. local SVData = {}
  13. local SVDataIndex = 0
  14.  
  15. -- Whether the player is currently interacting with something
  16. local interacting = false
  17.  
  18. -- Whether the player wants to view his history
  19. local showHistoryAtLogin = true
  20.  
  21. -- Initialise the Saved Variables File
  22. -- Found in EsoHead addon ( thanks )
  23. local function InitSavedVariables(...)
  24.     SVData = {
  25.         ["History"] = ZO_SavedVars:NewAccountWide("XrysGatherer_SavedVariables", 1, "History", SVDefault)
  26.     }
  27.     SVDataIndex = 1
  28. end
  29.  
  30. -- Check if the item already exists in the database in that zone and location ( or very close to it )
  31. -- Variation of the test found in Esohead addon ( thanks )
  32. local function SVDataExists(xPos,yPos,zone,name)
  33.     local found = false
  34.     local zoneData = SVData["History"][zone]
  35.     if not zoneData then return false end
  36.     local nameData = zoneData[name]
  37.     if not nameData then return false end
  38.     for i,v in pairs(nameData) do
  39.         local x,y = v["X"],v["Y"]
  40.         if math.abs(xPos - x) < 0.005 and math.abs(yPos - y) < 0.005 then
  41.             found = true
  42.             break
  43.         end    
  44.     end
  45.     if found then return true end
  46.     return false
  47. end
  48.  
  49. -- Update Routine to track harvest interactions which do not have an event at present
  50. function XrysGatherer_Update(...)
  51.  
  52.     -- Is the player interacting with something ?
  53.     local playerInteracting = IsPlayerInteractingWithObject()
  54.     if not playerInteracting then interacting = false return end
  55.  
  56.     -- Check if the Interaction Type is Harvest
  57.     local interactMode = GetInteractionType()
  58.     if interactMode  ~= INTERACTION_HARVEST then return end
  59.  
  60.     -- Check if we are still processing the last interaction update cycle
  61.     if interacting then return end
  62.     interacting = true
  63.  
  64.     -- Get some important information into variables for use later
  65.     local unitID = "player"
  66.     local zone = GetUnitZone(unitID)
  67.     local xPos,yPos,zPos = GetMapPlayerPosition(unitID)
  68.     local action, name, blocked, extra, context = GetGameCameraInteractableActionInfo()
  69.     local dateValue = GetDate()
  70.     local timeValue = GetTimeString()
  71.  
  72.     -- Just in case it thinks crafting is a harvestable object
  73.     if action == "Use" then
  74.         ChatMsg:AddMessage(string.format("Action: %s Name: %s Mode: %d Extra: %d",action,name,interactMode,extra))
  75.         return
  76.     end
  77.  
  78.     -- Does the node exist in the database ?
  79.     local nodeExists = SVDataExists(xPos,yPos,zone,name)
  80.     local NewOrOld = "New"
  81.     if nodeExists then NewOrOld = "Old" end
  82.  
  83.     -- Display information on the screen regardless if it is an old or new node
  84.     ChatMsg:AddMessage(string.format("[%s] %s: %s at ( x:%0.3f, y:%0.3f ) in %s",NewOrOld,action,name,xPos,yPos,zone))
  85.  
  86.     -- Only update the saved variable file if the node doesn't exist in there yet
  87.     if not nodeExists then
  88.         ChatMsg:AddMessage("Adding Harvest Node to Database")
  89.         SVData = SVData or {}
  90.         SVData["History"]                       = SVData["History"] or {}
  91.         SVData["History"]                       = SVData["History"] or {}
  92.         SVData["History"][zone]                 = SVData["History"][zone] or {}
  93.         SVData["History"][zone][name]           = SVData["History"][zone][name] or {}
  94.  
  95.         SVDataIndex = #SVData["History"][zone][name] + 1
  96.  
  97.         SVData["History"][zone][name][SVDataIndex]              = SVData["History"][zone][name][SVDataIndex] or {}
  98.         SVData["History"][zone][name][SVDataIndex]["Action"]    = action
  99.         SVData["History"][zone][name][SVDataIndex]["X"]         = xPos
  100.         SVData["History"][zone][name][SVDataIndex]["Y"]         = yPos
  101.         SVData["History"][zone][name][SVDataIndex]["Date"]      = dateValue
  102.         SVData["History"][zone][name][SVDataIndex]["Time"]      = timeValue
  103.     end
  104.  
  105.     ChatMsg:AddMessage("Traversing Harvest History")
  106.     for history,sv in pairs(SVData) do         
  107.         if history == "History" then
  108.             for zone, t1 in pairs(SVData[history]) do
  109.                 for item, t2 in pairs(SVData[history][zone]) do
  110.                     for index, t3 in pairs(SVData[history][zone][item]) do
  111.                         local data = SVData[history][zone][item][index]
  112.                         ChatMsg:AddMessage(string.format("%d: %s %s in %s at %0.3f,%0.3f",index,item,tostring(data["Action"]),zone,data["X"],data["Y"]))
  113.                     end
  114.                 end
  115.             end
  116.         end
  117.     end
  118.  
  119. end
  120.  
  121. -- Our Addon is loaded so we can start work
  122. local function AddOnLoaded(eventID,addon)
  123.     if addon ~= addonName then return end
  124.     EventMgr:UnregisterForEvent(addonName,eventID)
  125.     ChatMsg:AddMessage(string.format("%s %s Loaded",addonName,addonVersion))
  126.     InitSavedVariables()
  127.  
  128.         -- Have to have this here at this point to get the table traversing properly that session.  
  129.         -- If I remove this line the function error appears again and it won't traverse.
  130.     SVData["History"] = {}
  131. end
  132.  
  133. -- Track addons loading
  134. EventMgr:RegisterForEvent( addonName ,EVENT_ADD_ON_LOADED , AddOnLoaded )

Here is a screenshot of what is happening when I try and traverse through the table.

If I change the traversing to the following in the hopes of bypassing the other stuff I get the same problem:

Lua Code:
  1. for zone, t1 in pairs(SVData[history]) do
  2.                 for item, t2 in pairs(SVData[history][zone]) do
  3.                     for index, t3 in pairs(SVData[history][zone][item]) do
  4.                         local data = SVData[history][zone][item][index]
  5.                         ChatMsg:AddMessage(string.format("%d: %s %s in %s at %0.3f,%0.3f",index,item,tostring(data["Action"]),zone,data["X"],data["Y"]))
  6.                     end
  7.                 end
  8.             end

Again, only if the data exists when logging in.
Attached Thumbnails
Click image for larger version

Name:	Table Traversing Problem.jpg
Views:	567
Size:	270.9 KB
ID:	24  

Last edited by Xrystal : 03/02/14 at 04:51 PM.
  Reply With Quote
03/02/14, 02:31 PM   #7
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
That's the name of my addon saved variable table.

I've been putting this at the top of my addons, to make things a bit easier:
local addonName = "XrysGatherer"
local addonVersion = "0.0.1"
local addonSV = addonName.."_SavedVariables"


In the gather addon it works out as "XrysGatherer_SavedVariables". That's why I don't get, writing to it works fine .. but reading from it seems to be a bit messed up unless you are looking for a specific element like I do to identify an existing element.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Problem Traversing the Saved Variables Table


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off