annotate Scanner.lua @ 81:58617c7827fa

Item refilling should now be working. Probably very slow if your bags, bank or guild bank is filled with over 200 unique items or so (needs some real testing, but know that it is a known (possible) issue).
author Zerotorescue
date Thu, 06 Jan 2011 01:01:25 +0100
parents c0bf2ddb5288
children f885805da5d6
rev   line source
Zerotorescue@80 1 local addon = select(2, ...);
Zerotorescue@80 2 local mod = addon:NewModule("Scanner", "AceEvent-3.0");
Zerotorescue@80 3
Zerotorescue@80 4 addon.Locations = {
Zerotorescue@80 5 Bag = 0,
Zerotorescue@80 6 Bank = 1,
Zerotorescue@80 7 Guild = 2,
Zerotorescue@80 8 };
Zerotorescue@80 9
Zerotorescue@80 10 local Mover, paused;
Zerotorescue@80 11 local itemCache = {};
Zerotorescue@80 12
Zerotorescue@80 13 local function GetItemID(link)
Zerotorescue@80 14 return tonumber(link:match("|Hitem:([-0-9]+):"));
Zerotorescue@80 15 end
Zerotorescue@80 16
Zerotorescue@80 17 function mod:ClearCache()
Zerotorescue@80 18 table.wipe(itemCache);
Zerotorescue@80 19 end
Zerotorescue@80 20
Zerotorescue@80 21 function mod:CacheLocation(location, remember)
Zerotorescue@80 22 if location == addon.Locations.Bag or location == addon.Locations.Bank then
Zerotorescue@80 23 -- Reset cache just in case it was filled
Zerotorescue@80 24 self:ClearCache();
Zerotorescue@80 25
Zerotorescue@80 26 local start, stop;
Zerotorescue@80 27 if location == addon.Locations.Bag then
Zerotorescue@80 28 start = 0;
Zerotorescue@80 29 stop = NUM_BAG_SLOTS;
Zerotorescue@80 30 else
Zerotorescue@80 31 -- If we requested the bank then we don't want the bag info
Zerotorescue@80 32 start = ( NUM_BAG_SLOTS + 1 );
Zerotorescue@80 33 stop = ( NUM_BAG_SLOTS + NUM_BANKBAGSLOTS );
Zerotorescue@80 34 end
Zerotorescue@80 35
Zerotorescue@80 36 -- Go through all our bags, including the backpack
Zerotorescue@81 37 for i = start, ((location == addon.Locations.Bag and stop) or (location == addon.Locations.Bank and (stop + 1))) do -- if scanning bags stop at normal bag slot, if scanning bank, stop one later to allow BANK_CONTAINER to be scanned too
Zerotorescue@80 38 -- Scan the default 100 slots whenever we're at a non-existing index
Zerotorescue@80 39 local bagId = (i == (stop + 1) and BANK_CONTAINER) or i;
Zerotorescue@80 40 local slotId = GetContainerNumSlots(bagId);
Zerotorescue@80 41
Zerotorescue@80 42 while slotId ~= 0 do
Zerotorescue@80 43 -- A not equal-comparison should be quicker than a larger than-comparison
Zerotorescue@80 44
Zerotorescue@80 45 local itemId = GetContainerItemID(bagId, slotId);
Zerotorescue@80 46 local itemCount = itemId and select(2, GetContainerItemInfo(bagId, slotId));
Zerotorescue@80 47
Zerotorescue@80 48 if itemId and itemCount and itemCount > 0 then
Zerotorescue@80 49 local itemMove;
Zerotorescue@80 50 if not itemCache[itemId] then
Zerotorescue@80 51 -- If this is the first time we see this item, make a new object
Zerotorescue@81 52 itemMove = addon.ContainerItem:New();
Zerotorescue@81 53 itemCache[itemId] = itemMove;
Zerotorescue@80 54 else
Zerotorescue@80 55 -- If we had this item in another slot too
Zerotorescue@80 56 itemMove = itemCache[itemId];
Zerotorescue@80 57 end
Zerotorescue@80 58
Zerotorescue@81 59 itemMove:AddLocation(bagId, slotId, itemCount);
Zerotorescue@80 60 end
Zerotorescue@80 61
Zerotorescue@80 62 -- Continue scanning a different slot
Zerotorescue@80 63 slotId = (slotId - 1);
Zerotorescue@80 64 end
Zerotorescue@80 65 end
Zerotorescue@80 66 elseif location == addon.Locations.Guild then
Zerotorescue@80 67 -- Reset cache before we scan
Zerotorescue@80 68 self:ClearCache();
Zerotorescue@80 69
Zerotorescue@80 70 local tabId = GetCurrentGuildBankTab();
Zerotorescue@80 71 local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot
Zerotorescue@80 72
Zerotorescue@80 73 if tabId == nil or tabId < 1 then return; end
Zerotorescue@80 74
Zerotorescue@80 75 while slotId ~= 0 do
Zerotorescue@80 76 -- A not equal-comparison should be quicker than a larger than-comparison
Zerotorescue@80 77
Zerotorescue@80 78 -- If there is actually an item in this slot
Zerotorescue@80 79
Zerotorescue@80 80 local itemLink = GetGuildBankItemLink(tabId, slotId);
Zerotorescue@80 81 local itemId = itemLink and GetItemId(itemLink);
Zerotorescue@80 82 local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId));
Zerotorescue@80 83
Zerotorescue@80 84 if itemLink and itemId and itemCount and itemCount > 0 then
Zerotorescue@80 85 local itemMove;
Zerotorescue@80 86 if not itemCache[itemId] then
Zerotorescue@80 87 -- If this is the first time we see this item, make a new object
Zerotorescue@81 88 itemMove = addon.ContainerItem:New();
Zerotorescue@81 89 itemCache[itemId] = itemMove;
Zerotorescue@80 90 else
Zerotorescue@80 91 -- If we had this item in another slot too
Zerotorescue@80 92 itemMove = itemCache[itemId];
Zerotorescue@80 93 end
Zerotorescue@80 94
Zerotorescue@81 95 itemMove:AddLocation(tabId, slotId, itemCount);
Zerotorescue@80 96 end
Zerotorescue@80 97
Zerotorescue@80 98 -- Continue scanning a different slot
Zerotorescue@80 99 slotId = (slotId - 1);
Zerotorescue@80 100 end
Zerotorescue@80 101 else
Zerotorescue@80 102 error("Invalid location provided for the local _GetItemCount. Must be Bank or Guild.");
Zerotorescue@80 103 end
Zerotorescue@80 104
Zerotorescue@80 105 if not remember then
Zerotorescue@80 106 -- Copy the table as clearing the cache wipes it empty (and tables are passed by reference)
Zerotorescue@80 107 local cacheCopy = CopyTable(itemCache);
Zerotorescue@80 108
Zerotorescue@80 109 self:ClearCache();
Zerotorescue@80 110
Zerotorescue@80 111 return cacheCopy;
Zerotorescue@80 112 end
Zerotorescue@80 113 end
Zerotorescue@80 114
Zerotorescue@80 115 function mod:Scan(location)
Zerotorescue@80 116 -- We might pause the scanning when we invoke moves ourself
Zerotorescue@80 117 if paused then
Zerotorescue@80 118 return;
Zerotorescue@80 119 end
Zerotorescue@80 120
Zerotorescue@80 121 local playerName = UnitName("player");
Zerotorescue@80 122
Zerotorescue@80 123 self:CacheLocation(location, true);
Zerotorescue@80 124
Zerotorescue@80 125 -- Go through all groups
Zerotorescue@80 126 for groupName, values in pairs(addon.db.profile.groups) do
Zerotorescue@80 127 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
Zerotorescue@80 128
Zerotorescue@80 129 if values.items and trackAt[playerName] then
Zerotorescue@80 130 -- Is this character interested in this data?
Zerotorescue@80 131
Zerotorescue@80 132 local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock");
Zerotorescue@80 133
Zerotorescue@80 134 -- Go through all items
Zerotorescue@80 135 for itemId, _ in pairs(values.items) do
Zerotorescue@80 136
Zerotorescue@81 137 -- Check if we have enough items local (but only do so if this location also has enough available)
Zerotorescue@81 138 local missingItems = itemCache[itemId] and (minLocalStock - addon:GetLocalItemCount(itemId, groupName));
Zerotorescue@80 139
Zerotorescue@81 140 if itemCache[itemId] and missingItems > 0 then
Zerotorescue@80 141 -- Check how many are available
Zerotorescue@81 142 local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
Zerotorescue@80 143
Zerotorescue@80 144 if availableItems > 0 then
Zerotorescue@80 145 print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")");
Zerotorescue@80 146
Zerotorescue@80 147 Mover:AddMove(itemId, missingItems);
Zerotorescue@80 148 else
Zerotorescue@81 149 print("Insufficient " .. IdToItemLink(itemId));
Zerotorescue@80 150 end
Zerotorescue@80 151 end
Zerotorescue@80 152 end
Zerotorescue@80 153 end
Zerotorescue@80 154 end
Zerotorescue@80 155
Zerotorescue@80 156 self:ClearCache();
Zerotorescue@80 157
Zerotorescue@81 158 if Mover:HasMoves() then
Zerotorescue@81 159 StaticPopupDialogs["InventoriumRefill"] = {
Zerotorescue@81 160 text = "There are items that can be refilled from this location, do you wish to proceed?",
Zerotorescue@81 161 button1 = YES,
Zerotorescue@81 162 button2 = NO,
Zerotorescue@81 163 OnAccept = function()
Zerotorescue@81 164 mod:Pause();
Zerotorescue@81 165 Mover:BeginMove(location, self.Unpause);
Zerotorescue@81 166 end,
Zerotorescue@81 167 timeout = 0,
Zerotorescue@81 168 whileDead = 1,
Zerotorescue@81 169 hideOnEscape = 1,
Zerotorescue@81 170 };
Zerotorescue@81 171 StaticPopup_Show("InventoriumRefill");
Zerotorescue@81 172 end
Zerotorescue@81 173 end
Zerotorescue@81 174
Zerotorescue@81 175 local function BANKFRAME_CLOSED()
Zerotorescue@81 176 addon:Debug("Scanner:BANKFRAME_CLOSED");
Zerotorescue@81 177
Zerotorescue@81 178 mod:UnregisterEvent("BANKFRAME_CLOSED");
Zerotorescue@81 179
Zerotorescue@81 180 StaticPopup_Hide("InventoriumRefill");
Zerotorescue@80 181 end
Zerotorescue@80 182
Zerotorescue@80 183 local function BANKFRAME_OPENED()
Zerotorescue@81 184 addon:Debug("Scanner:BANKFRAME_OPENED");
Zerotorescue@81 185
Zerotorescue@81 186 mod:RegisterEvent("BANKFRAME_CLOSED", BANKFRAME_CLOSED);
Zerotorescue@81 187
Zerotorescue@80 188 -- Scan once when the bank is opened, but no need to scan after
Zerotorescue@80 189 mod:Scan(addon.Locations.Bank);
Zerotorescue@80 190 end
Zerotorescue@80 191
Zerotorescue@80 192 -- Remember which tabs were scanned and don't scan them again
Zerotorescue@80 193 local guildBankTabsScanned = {};
Zerotorescue@80 194
Zerotorescue@80 195 local function GUILDBANKFRAME_CLOSED()
Zerotorescue@81 196 addon:Debug("Scanner:GUILDBANKFRAME_CLOSED");
Zerotorescue@81 197
Zerotorescue@81 198 table.wipe(guildBankTabsScanned);
Zerotorescue@81 199
Zerotorescue@80 200 mod:UnregisterEvent("GUILDBANKFRAME_CLOSED");
Zerotorescue@80 201 mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED");
Zerotorescue@80 202
Zerotorescue@81 203 StaticPopup_Hide("InventoriumRefill");
Zerotorescue@80 204 end
Zerotorescue@80 205
Zerotorescue@80 206 local function GUILDBANKBAGSLOTS_CHANGED()
Zerotorescue@80 207 if not guildBankTabsScanned[GetCurrentGuildBankTab()] then
Zerotorescue@81 208 addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning");
Zerotorescue@81 209
Zerotorescue@80 210 mod:Scan(addon.Locations.Guild);
Zerotorescue@80 211 guildBankTabsScanned[GetCurrentGuildBankTab()] = true;
Zerotorescue@80 212 else
Zerotorescue@80 213 addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning");
Zerotorescue@80 214 end
Zerotorescue@80 215 end
Zerotorescue@80 216
Zerotorescue@80 217 local function GUILDBANKFRAME_OPENED()
Zerotorescue@81 218 addon:Debug("Scanner:GUILDBANKFRAME_OPENED");
Zerotorescue@81 219
Zerotorescue@80 220 table.wipe(guildBankTabsScanned);
Zerotorescue@80 221
Zerotorescue@80 222 mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED);
Zerotorescue@80 223 mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED);
Zerotorescue@80 224 end
Zerotorescue@80 225
Zerotorescue@80 226 function mod:OnEnable()
Zerotorescue@80 227 -- Scan once when the bankframe is opened
Zerotorescue@80 228 mod:RegisterEvent("BANKFRAME_OPENED", BANKFRAME_OPENED);
Zerotorescue@80 229 mod:RegisterEvent("GUILDBANKFRAME_OPENED", GUILDBANKFRAME_OPENED);
Zerotorescue@80 230
Zerotorescue@80 231 Mover = addon:GetModule("Mover");
Zerotorescue@80 232 end
Zerotorescue@80 233
Zerotorescue@80 234 function mod:OnDisable()
Zerotorescue@80 235 Mover = nil;
Zerotorescue@80 236
Zerotorescue@80 237 -- Bank
Zerotorescue@80 238 mod:UnregisterEvent("BANKFRAME_OPENED");
Zerotorescue@80 239
Zerotorescue@80 240 -- Guild
Zerotorescue@80 241 GUILDBANKFRAME_CLOSED();
Zerotorescue@80 242 mod:UnregisterEvent("GUILDBANKFRAME_OPENED");
Zerotorescue@80 243 end
Zerotorescue@80 244
Zerotorescue@80 245 function mod:Pause()
Zerotorescue@80 246 paused = true;
Zerotorescue@80 247 end
Zerotorescue@80 248
Zerotorescue@80 249 function mod:Unpause()
Zerotorescue@80 250 paused = nil;
Zerotorescue@80 251 end