annotate Modules/Scanner.lua @ 88:f1c035694545

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