• 0

    posted a message on How to read tradeskill info reliably
    Quote from lilsparky

    i think the close trade skill problem is due to armory monkeying with that function. disable it and see if you get those extra update events.


    Armory does interfere with the close function, I checked the code. Using the above code makes it work with armory and I can't see why it shouldn't work without armory. I can only assume that the author or Armory had the same difficulties that I have reading the items reliably.

    I will have to use the tradelink eventually but this is requires some support libraries (you mentioned the names). I did check libperiodictable but couldn't figure out from the code how to convert spell-links to item-links. I know about the TradeLinks addon (only provides spell-ids).
    Posted in: Lua Code Discussion
  • 0

    posted a message on How to read tradeskill info reliably
    This is the code I ended up with. It seems to be reliable. The debug code (prints) will be removed eventually. :-)

    function GuildAdsTradeSkillDataType:enterWorld()
        self:UnregisterEvent("PLAYER_ENTERING_WORLD");
        self:RegisterEvent("TRADE_SKILL_SHOW", "onEvent");
        self:RegisterEvent("TRADE_SKILL_UPDATE", "onEvent");
        self:RegisterEvent("TRADE_SKILL_CLOSE", "onEvent");
    end
    
    -- Nearly impossible to get reliable tradeskill information. 
    local Orig_CloseTradeSkill = CloseTradeSkill
    function CloseTradeSkill()
        GuildAdsTradeSkillDataType.tradeSkillWindowOpen=false;
        -- call the original CloseTradeSkill
        Orig_CloseTradeSkill();
    end
    
    function GuildAdsTradeSkillDataType:onEvent(event, arg1)
        GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: event="..tostring(event));
        ChatFrame1:AddMessage("GuildAdsTradeSkillDataType: event="..tostring(event));
        if event=="TRADE_SKILL_SHOW" then
            GuildAdsTradeSkillDataType.tradeSkillWindowOpen=true;
            GuildAdsTradeSkillDataType:UpdateTradeSkills();
        elseif event=="TRADE_SKILL_CLOSE" then
            GuildAdsTradeSkillDataType.tradeSkillWindowOpen=false;
        elseif GuildAdsTradeSkillDataType.tradeSkillWindowOpen then
            GuildAdsTradeSkillDataType:UpdateTradeSkills();
        end
    end
    
    function GuildAdsTradeSkillDataType:UpdateTradeSkills()
        local skillId = GuildAdsSkillDataType:getIdFromName(GetTradeSkillLine());
        if skillId > 0 and not IsTradeSkillLinked() then
            local item, colddown, kind, open, itemRecipe, minMade, maxMade, q;
            local tmp = {}
            local added, deleted = 0, 0;
            local t = self:getTableForPlayer(GuildAds.playerName);
    
            -- Check the TradeSkill UI to see if any filters are enabled.
            local fullListShown = true
            if TradeSkillFrameAvailableFilterCheckButton then
                fullListShown = fullListShown and not TradeSkillFrameAvailableFilterCheckButton:GetChecked()
                --GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: button = "..tostring(TradeSkillFrameAvailableFilterCheckButton:GetChecked() and "checked" or "not checked"))
            end
            if TradeSkillFrameEditBox then
                fullListShown = fullListShown and (TradeSkillFrameEditBox:GetText() == "" or TradeSkillFrameEditBox:GetText() == SEARCH)
                --GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: text = "..tostring(TradeSkillFrameEditBox:GetText()))
            end
            if TradeSkillInvSlotDropDown then
                local dd = UIDropDownMenu_GetSelectedID(TradeSkillInvSlotDropDown)
                fullListShown = fullListShown and (dd == 1 or not dd)
                --GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: InvDropDown = "..(UIDropDownMenu_GetSelectedID(TradeSkillInvSlotDropDown) or ""))
            end
            if TradeSkillSubClassDropDown then
                local dd = UIDropDownMenu_GetSelectedID(TradeSkillSubClassDropDown)
                fullListShown = fullListShown and (dd == 1 or not dd)
                --GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: ClassDropDown = "..(UIDropDownMenu_GetSelectedID(TradeSkillSubClassDropDown) or ""))
            end
            
            -- Check to see if there are any headers. If not, item info is most likely not available yet.
            local headers=false
            for i=1,GetNumTradeSkills() do
                _, kind, _, open = GetTradeSkillInfo(i);
                if (kind == "header") then
                    headers = true
                end
            end
            if not headers then
                GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: no headers found")
                ChatFrame1:AddMessage("GuildAdsTradeSkillDataType: no headers found")
                return
            end
            
            -- Check for new tradeskills
            for i=1,GetNumTradeSkills() do
                _, kind, _, open = GetTradeSkillInfo(i);
                if (kind ~= "header") then
                    item = GetTradeSkillItemLink(i);
                    
                    minMade, maxMade = GetTradeSkillNumMade(i);
                    itemRecipe = GetTradeSkillRecipeLink(i);
                    if item then
                        _, item = GuildAds_ExplodeItemRef(item);
                        tmp[item]=true;
                        -- don't share cooldown, causes too much update
                        --[[
                        cooldown = GetTradeSkillCooldown(i) 
                        if cooldown then
                            cooldown = cooldown / 60 + GuildAdsDB:GetCurrentTime();
                        end;
                        ]]
                        _, itemRecipe = GuildAds_ExplodeItemRef(itemRecipe);
                        q=nil;
                        if minMade~=1 or maxMade~=1 then
                            q=tostring(minMade);
                            if maxMade~=minMade then
                                q=q.."-"..tostring(maxMade);
                            end
                        end
                        
                        -- if not (t[item] and t[item].e and t[item].q) then
                        if not (t[item]) then
                            self:set(GuildAds.playerName, item, { s=skillId, e=itemRecipe, q=q });
                            added = added + 1
                        elseif not t[item].s then
                            t[item].s = skillId
                        end
                    end
                else
                    fullListShown = fullListShown and open
                end
            end
            
            GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: Full List Shown: "..(fullListShown and "true" or "false"))
            ChatFrame1:AddMessage("GuildAdsTradeSkillDataType: Full List Shown: "..(fullListShown and "true" or "false"))
            
            -- delete items not found in the above code
            if fullListShown then
                local tmp2 = {};
                local craft = self:getTableForPlayer(GuildAds.playerName);
                for item, data in pairs(craft) do
                    if (not tmp[item]) and (item ~= "_u") and (data.s == skillId) then
                        tinsert(tmp2, item);
                    end
                end
                for _, item in pairs(tmp2) do
                    self:set(GuildAds.playerName, item, nil);
                    deleted = deleted + 1
                end
            end
            GuildAds_ChatDebug(GA_DEBUG_PLUGIN, "GuildAdsTradeSkillDataType: Updating tradeskill information (%s added, %s deleted)", added, deleted);
            ChatFrame1:AddMessage("GuildAdsTradeSkillDataType: Updating tradeskill information ("..added.." added, "..deleted.." deleted)");
        end
    end
    Posted in: Lua Code Discussion
  • 0

    posted a message on How to read tradeskill info reliably
    Quote from lilsparky
    are you saying it's inconsistent? throw some debugging code in there and see when you've got a spell link vs an item link. see if it's consistent and if so, what the circumstances are. it sounds to me like a bug in your code, honestly. what you pasted seems to have been edited down since it's missing an end. can you post a more complete bit of code?

    what exactly is your goal here, anyway? to figure out what items a person can make? if so, you might try getting the person's trade links (spellLink, tradeLink = GetSpellLink(tradeID or tradeName)), decoding them (download TradeLinks from wowinterface), then using a database like libperiodictable to connect spell links to items. all without having to futz with the tradeskill api at all.


    Ideally, I would switch to using trade: links, but there exist no library that can decode a trade: link to both spell: and item: link. Only decoding to spell: link is possible right now. And I need both.

    Anyway, I have come the problem a bit closer. Using the TRADE_SKILL_UPDATE, I can get a clearer view of the problem. And it is something like this: When opening the profession window, I get TRADE_SKILL_UPDATE fired a number of times before TRADE_SKILL_SHOW. This is ignored by my code. I will also ignore the result if TRADE_SKILL_SHOW results in a list without headers (occurs often it seems). So now I gather items if TRADE_SKILL_SHOW fires or if TRADE_SKILL_UPDATE fires after TRADE_SKILL_SHOW (and before TRADE_SKILL_CLOSE) and then only if there are any headers. This part seems reliable.

    The unreliable part comes when closing the tradeskill window. If closed by clicking the icon in the spellbook, TRADE_SKILL_SHOW fires twice and all is well. If however the tradeskill window is closed by clicking the close icon on the tradeskill window, then TRADE_SKILL_UPDATE fires and the tradeskill functions now report that no items/spells are available. This causes my code to erase the database of the previously recorded item/spell links. Then a number of TRADE_SKILL_UPDATE fires where some items are added and others deleted. The last TRADE_SKILL_UPDATE fires again and now all tradeskill items/spells are available again. And then the TRADE_SKILL_CLOSE event fires.

    So, when TRADE_SKILL_UPDATE between the TRADE_SKILL_SHOW and the TRADE_SKILL_CLOSE event, the item/spell returned by GetTradeSkillItemLink() is not reliable IF (and only if) you close the window clicking on the close icon.

    I'll try to hook the close function and stop any calls to GetTradeSkillItemLink() from happening until the next TRADE_SKILL_SHOW event fires.
    Posted in: Lua Code Discussion
  • 0

    posted a message on How to read tradeskill info reliably
    Thank you for your details, but given the skeleton code I presented, the item variable will occasionally hold the spell: link instead of the item: link. This may be a fallback as per design by Blizzard. I specifically check if the item variable is non-nil before I act on it and I either get item: link or spell: links (even for cooking I get spell: links).

    I'll try to use TRADE_SKILL_UPDATE again (used it before but only made the situation worse). Maybe I can rig something more reliable scanning for headers. I'll try.
    Posted in: Lua Code Discussion
  • 0

    posted a message on How to read tradeskill info reliably
    Quote from Torhal
    I can't even begin to figure out what's happening with incomplete code to reference...

        if skillId > 0 and not IsTradeSkillLinked() then
           -- read tradeskill info
        end


    You suggest my problem is in the function whose code you have copied, otherwise the other code would be faulty.

    The tradeskill info is read like this:

            for i=1,GetNumTradeSkills() do
                _, kind, _, open = GetTradeSkillInfo(i);
                if (kind ~= "header") then
                    item = GetTradeSkillItemLink(i);
                    
                    minMade, maxMade = GetTradeSkillNumMade(i);
                    itemRecipe = GetTradeSkillRecipeLink(i);
                    if item then
    -- item assumed valid, but is occasionally spell links
    -- item link is stored (even if it is a spell link, has to work for enchanting as well)
               end
            end


    The get IdFromName function simply returns a number for the tradeskill or nothing if the tradeskill isn't known to the addon.

    I don't know any other way to read the tradeskill info. Is there any other way?
    Posted in: Lua Code Discussion
  • 0

    posted a message on How to read tradeskill info reliably
    I have some code like this:

    function onEvent(event, arg1)
        if event=="TRADE_SKILL_SHOW" then
            tradeSkillWindowOpen=true;
            UpdateTradeSkills();
        elseif event=="TRADE_SKILL_CLOSE" then
            tradeSkillWindowOpen=false;
        end
    end


    Only the two events mentioned are hooked. This function is called when the first event fires:

    function UpdateTradeSkills()
        local skillId = getIdFromName(GetTradeSkillLine());
        if skillId > 0 and not IsTradeSkillLinked() then
           -- read tradeskill info
        end
    end


    This almost works. Problem is that occasionally, the tradeskill info being read by GetTradeSkillItemLink() does not return an item: link but a spell: link. I don't know which situation makes it do that (haven't done it myself) but other players in my guild experience it. I think it happens upon login, if the tradeskill window is opened very early on, before all items have been fetched from the server, but this is just my guess.

    I noticed that Armory addon author has decided to hook the CloseTradeSkill() function (catches the close button on the tradeskill window only, not clicking the profession icon in the spellbook) possibly because he had the same problem.

    Anyway, does anyone know how to read the data reliably when the tradeskill window is open?

    Is the 'Armory' method the only reliable way? Or is that unreliable as well, just less unreliable?
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    I believe you are right and I was digging through the code (I didn't write that part of the addon) and found out that JoinPermanentChannel was called when the event PLAYER_ENTERING_WORLD fired. I believe this was added as a failsafe and I have added a 20 second delay on it. I am not sure if it should be removed entirely as I seem to remember that channels aren't joined upon login when you logged out during taxi.

    Sorry for the noise. :-/
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    Hmm I believe other addons can help do that. It should be possible to have some reliable code to join channels after the general channels are joined.

    But I suspect the problem lies with JoinPermanentChannel, in that it gets the server to remember the channel to be joined upon next login. The client (or server) must get the channel order wrong and therefore join the channels in the wrong order.
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    Any hints at all?
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    Quote from Xinhuan
    If you aren't aware yet, channels that you join are saved server side. And this is synced by default so if you log on from a public computer, your chat channels will be downloaded and joined correctly.


    Yes, I noticed they were saved on the server, but this remains a problem. Sometimes my custom channel is joined prior to the General etc. channels.

    I join the channels in this situation (during load):

    if GetChannelList()==1 then
    joinWaitingChannels();
    end

    or if the addon receives this event:

    local onEvent = function(self, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
    if event=="CHAT_MSG_CHANNEL_NOTICE" then
    if arg1=="YOU_JOINED" and arg8==1 then
    joinWaitingChannels();
    end
    end
    ...

    What can go wrong in the above?
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    JoinPermanentChannel seems to store the channel joined in the save files somewhere and will therefore join the channel upon login automatically, whether I load the addon or not. If the normal channels (General etc) are joined late, the custom channel is joined first.
    Posted in: Lua Code Discussion
  • 0

    posted a message on JoinChannelByName deprecated?
    I read on http://wowprogramming.com/docs/api/JoinChannelByName that JoinChannelByName is deprecated. Is that true?

    The reason I ask is because I have switched to use JoinPermanentChannel instead, but it is causing trouble in that the channel is join immedately at login, sometimes as channel numer 1, displacing the rest of the channels.

    But JoinPermanentChannel is the only one supporting passwords otherwise I would have tried using JoinTemporaryChannel.

    Is there a different way to join a channel that mimics the behaviour of JoinChannelByName should it be deprecated?
    Posted in: Lua Code Discussion
  • 0

    posted a message on Using a..b..c instead of string.format...
    Hmm yes, benchmarking confirms it. string.format is faster if you know the string to be inserted is a number (and you use %d). If, however, strings are to be inserted, then concatenation is the fastest solution.
    Posted in: Libraries
  • 0

    posted a message on Using a..b..c instead of string.format...
    Great. :-)
    Posted in: Libraries
  • 0

    posted a message on Using a..b..c instead of string.format...
    I have a question about the creation of string garbage when using either this:

    str = a..">"..b..">"..c

    compares to this:

    str = string.format(str,"%s>%s>%s",a,b,c)

    Which of the 2 methods create the most string garbage and which would be fastest to execute?

    I'd like to have the result in favour of the first method in that it works with zero-terminated strings which the second method does not.
    Posted in: Libraries
  • To post a comment, please or register a new account.