WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Problem reading Item tooltips for Recipes (https://www.wowinterface.com/forums/showthread.php?t=56742)

MuffinManKen 10-03-18 08:48 PM

Problem reading Item tooltips for Recipes
 
I'm trying to read the tooltip data for a large number of items, but the basic code I'm using is having an issue; the tooltip is often incomplete. I write up a minimal test case and paste it into WoWLua using Design: Nightmare Tear as the item. No matter how many times I run it, the part of the recipe that is supposed to be after the item info is never there (mats, required skill).

Is there an error in my code or am I just not understanding how this should work?

Lua Code:
  1. tt_frame = tt_frame or CreateFrame("GameTooltip", "MuffinItemCacheTooltip", UIParent, "GameTooltipTemplate")
  2.  
  3. function myOnTooltipSetItem(self, arg1, arg2, arg3)
  4. print("myOnTooltipSetItem", arg1, arg2, arg3)
  5.     local item_name, item_link = self:GetItem()
  6.  
  7.     if(not item_link) then
  8.         print("no item link, returning", item_name, item_link);
  9.         return;
  10.     end;
  11.  
  12.     local item_id = tonumber(string.match(item_link, "item:([%d]+):"))
  13.     local printable = gsub(item_link, "\124", "\124\124");
  14.     print(item_name, item_link, printable,  item_id)
  15.  
  16.     local tt = {}
  17.  
  18.     for i=1,tt_frame:NumLines() do
  19.         local textLeft =  _G["MuffinItemCacheTooltipTextLeft"..i]:GetText()
  20.         local textRight = _G["MuffinItemCacheTooltipTextRight"..i]:GetText()
  21.         table.insert(tt, textLeft)
  22.         table.insert(tt, textRight)
  23.     end
  24.  
  25.     self:Hide();
  26.  
  27.     print("item id:", "   ", item_id, table.concat(tt," "))
  28.  
  29.  
  30. end
  31. tt_frame:SetScript("OnTooltipSetItem", myOnTooltipSetItem)
  32.  
  33. function TestTT(p_item_id)
  34.    print("----------------")
  35.    tt_frame:SetOwner(UIParent,"ANCHOR_NONE")
  36.    tt_frame:SetItemByID(p_item_id)
  37.  
  38. end
  39.  
  40. TestTT(49112)

kurapica.igas 10-03-18 11:05 PM

I modify the code with my lib, if I use thread to call the myOnTooltipSetItem and make it wait until next OnUpdate, I get the require material and level texts.

So those text aren't generated together, we need a little delay to get all the result.

Lua Code:
  1. Scorpio "Test" ""
  2.  
  3. tt_frame = tt_frame or CreateFrame("GameTooltip", "MuffinItemCacheTooltip", UIParent, "GameTooltipTemplate")
  4.  
  5. __Async__()  -- mark the function as thread
  6. function myOnTooltipSetItem(self, arg1, arg2, arg3)
  7.     Next()  -- wait for the next OnUpdate
  8.    
  9.     print("myOnTooltipSetItem", arg1, arg2, arg3)
  10.     local item_name, item_link = self:GetItem()
  11.  
  12.     if(not item_link) then
  13.         print("no item link, returning", item_name, item_link);
  14.         return;
  15.     end;
  16.  
  17.     local item_id = tonumber(string.match(item_link, "item:([%d]+):"))
  18.     local printable = gsub(item_link, "\124", "\124\124");
  19.     print(item_name, item_link, printable,  item_id)
  20.  
  21.     local tt = {}
  22.  
  23.     for i=1,tt_frame:NumLines() do
  24.         local textLeft =  _G["MuffinItemCacheTooltipTextLeft"..i]:GetText()
  25.         local textRight = _G["MuffinItemCacheTooltipTextRight"..i]:GetText()
  26.         table.insert(tt, textLeft)
  27.         table.insert(tt, textRight)
  28.     end
  29.  
  30.     self:Hide();
  31.  
  32.     print("item id:", "   ", item_id, table.concat(tt," "))
  33.  
  34.  
  35. end
  36. tt_frame:SetScript("OnTooltipSetItem", myOnTooltipSetItem)
  37.  
  38. function TestTT(p_item_id)
  39.    print("----------------")
  40.    tt_frame:SetOwner(UIParent,"ANCHOR_NONE")
  41.    tt_frame:SetItemByID(p_item_id)
  42.  
  43. end
  44.  
  45. TestTT(49112)

You may use the C_Timer.After to do the trick.

MuffinManKen 10-03-18 11:35 PM

I worry about using timer-based things like this because it doesn't feel reliable. If the server takes a little bit longer to respond with the recipe details, I'll still end up with a partial tooltip. I wish there were a reliable event to say that the tooltip is fully loaded like there is with Item Info.

kurapica.igas 10-04-18 01:26 AM

I ran several test cases, if you access the item for the first time(start the game from the client), the require material and skill are query from the server, so wait a phase may not be enough, if you have accessed the item before, wait one phase will get those datas.

So, I re-modify the code like
Lua Code:
  1. Scorpio "Test" ""
  2.  
  3. tt_frame = tt_frame or CreateFrame("GameTooltip", "MuffinItemCacheTooltip", UIParent, "GameTooltipTemplate")
  4.  
  5. __Async__()  -- mark the function as thread
  6. function myOnTooltipSetItem(self, arg1, arg2, arg3)
  7.     self:SetScript("OnTooltipSetItem", nil)
  8.     Next()  -- wait for the next OnUpdate
  9.    
  10.     print("myOnTooltipSetItem", arg1, arg2, arg3)
  11.     local item_name, item_link = self:GetItem()
  12.  
  13.     if(not item_link) then
  14.         print("no item link, returning", item_name, item_link);
  15.         return;
  16.     end;
  17.  
  18.     local item_id = tonumber(string.match(item_link, "item:([%d]+):"))
  19.     local printable = gsub(item_link, "\124", "\124\124");
  20.     print(item_name, item_link, printable,  item_id)
  21.  
  22.     local tt = {}
  23.  
  24.     for i=1,tt_frame:NumLines() do
  25.         local textLeft =  _G["MuffinItemCacheTooltipTextLeft"..i]:GetText()
  26.         local textRight = _G["MuffinItemCacheTooltipTextRight"..i]:GetText()
  27.         table.insert(tt, textLeft)
  28.         table.insert(tt, textRight)
  29.     end
  30.  
  31.     self:Hide();
  32.  
  33.     print("item id:", "   ", item_id, table.concat(tt," "))
  34.  
  35.  
  36. end
  37.  
  38. __Async__()
  39. function TestTT(p_item_id)
  40.     if not GetItemInfo(p_item_id) then
  41.         -- wait 1 sec or the GET_ITEM_INFO_RECEIVED event
  42.         local evt, id = Wait(1, "GET_ITEM_INFO_RECEIVED")
  43.         if not (evt and id == p_item_id) then
  44.             return -- failed to fetch the item data
  45.         end
  46.     end
  47.     print("----------------")
  48.     tt_frame:SetOwner(UIParent,"ANCHOR_NONE")
  49.     tt_frame:SetScript("OnTooltipSetItem", myOnTooltipSetItem)
  50.     tt_frame:SetItemByID(p_item_id)
  51. end
  52.  
  53. TestTT(49112)

This time I run the TestTT as thread, and use the GetItemInfo to check if we have already cached the item's info, if not, we need wait the GET_ITEM_INFO_RECEIVED system event and check its first argument.

The API Wait I used is suspend the curoutine until the system event is fired or the delay of 1 sec is meet(since I can't make sure whether the item existed).

Then I check if the received item id is the target item, and continue the job.

-------------
I add the widget event handler in TestTT and remove it in the myOnTooltipSetItem, it seems the widget event would be fired several times since I delayed the hide of the gametooltip.

Rilgamon 10-04-18 03:20 AM

Login + 3 UI-Reloads will show the complete text. So your code is correct but the information is not yet available. So you should really use GET_ITEM_INFO_RECEIVED like kurapica.igas suggests.

MuffinManKen 10-04-18 03:48 PM

It all seems to be working well now, so thanks for all the feedback.

If anyone would get any use of it, you can grab a JSON dump of all items in WoW here:
https://github.com/MuffinManKen/WoWData


All times are GMT -6. The time now is 11:49 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI