| 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@82 | 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@82 | 102 		error("Invalid location provided for CacheLocation. 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@82 | 128 		local localItemData = self:GetOptionByKey(groupName, "localItemData"); | 
| Zerotorescue@80 | 129 | 
| Zerotorescue@82 | 130 		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 | 131 			-- Is this character interested in this data? | 
| Zerotorescue@80 | 132 | 
| Zerotorescue@80 | 133 			local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock"); | 
| Zerotorescue@80 | 134 | 
| Zerotorescue@80 | 135 			-- Go through all items | 
| Zerotorescue@80 | 136 			for itemId, _ in pairs(values.items) do | 
| Zerotorescue@80 | 137 | 
| Zerotorescue@81 | 138 				-- Check if we have enough items local (but only do so if this location also has enough available) | 
| Zerotorescue@81 | 139 				local missingItems = itemCache[itemId] and (minLocalStock - addon:GetLocalItemCount(itemId, groupName)); | 
| Zerotorescue@80 | 140 | 
| Zerotorescue@81 | 141 				if itemCache[itemId] and missingItems > 0 then | 
| Zerotorescue@80 | 142 					-- Check how many are available | 
| Zerotorescue@81 | 143 					local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0); | 
| Zerotorescue@80 | 144 | 
| Zerotorescue@80 | 145 					if availableItems > 0 then | 
| Zerotorescue@80 | 146 						print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")"); | 
| Zerotorescue@80 | 147 | 
| Zerotorescue@80 | 148 						Mover:AddMove(itemId, missingItems); | 
| Zerotorescue@80 | 149 					else | 
| Zerotorescue@81 | 150 						print("Insufficient " .. IdToItemLink(itemId)); | 
| Zerotorescue@80 | 151 					end | 
| Zerotorescue@80 | 152 				end | 
| Zerotorescue@80 | 153 			end | 
| Zerotorescue@80 | 154 		end | 
| Zerotorescue@80 | 155 	end | 
| Zerotorescue@80 | 156 | 
| Zerotorescue@80 | 157 	self:ClearCache(); | 
| Zerotorescue@80 | 158 | 
| Zerotorescue@81 | 159 	if Mover:HasMoves() then | 
| Zerotorescue@81 | 160 		StaticPopupDialogs["InventoriumRefill"] = { | 
| Zerotorescue@81 | 161 			text = "There are items that can be refilled from this location, do you wish to proceed?", | 
| Zerotorescue@81 | 162 			button1 = YES, | 
| Zerotorescue@81 | 163 			button2 = NO, | 
| Zerotorescue@81 | 164 			OnAccept = function() | 
| Zerotorescue@81 | 165 				mod:Pause(); | 
| Zerotorescue@81 | 166 				Mover:BeginMove(location, self.Unpause); | 
| Zerotorescue@81 | 167 			end, | 
| Zerotorescue@81 | 168 			timeout = 0, | 
| Zerotorescue@81 | 169 			whileDead = 1, | 
| Zerotorescue@81 | 170 			hideOnEscape = 1, | 
| Zerotorescue@82 | 171 			exclusive = 1, | 
| Zerotorescue@82 | 172 			enterClicksFirstButton = 1, | 
| Zerotorescue@81 | 173 		}; | 
| Zerotorescue@81 | 174 		StaticPopup_Show("InventoriumRefill"); | 
| Zerotorescue@81 | 175 	end | 
| Zerotorescue@81 | 176 end | 
| Zerotorescue@81 | 177 | 
| Zerotorescue@81 | 178 local function BANKFRAME_CLOSED() | 
| Zerotorescue@81 | 179 	addon:Debug("Scanner:BANKFRAME_CLOSED"); | 
| Zerotorescue@81 | 180 | 
| Zerotorescue@81 | 181 	mod:UnregisterEvent("BANKFRAME_CLOSED"); | 
| Zerotorescue@81 | 182 | 
| Zerotorescue@81 | 183 	StaticPopup_Hide("InventoriumRefill"); | 
| Zerotorescue@80 | 184 end | 
| Zerotorescue@80 | 185 | 
| Zerotorescue@80 | 186 local function BANKFRAME_OPENED() | 
| Zerotorescue@81 | 187 	addon:Debug("Scanner:BANKFRAME_OPENED"); | 
| Zerotorescue@81 | 188 | 
| Zerotorescue@81 | 189 	mod:RegisterEvent("BANKFRAME_CLOSED", BANKFRAME_CLOSED); | 
| Zerotorescue@81 | 190 | 
| Zerotorescue@80 | 191 	-- Scan once when the bank is opened, but no need to scan after | 
| Zerotorescue@80 | 192 	mod:Scan(addon.Locations.Bank); | 
| Zerotorescue@80 | 193 end | 
| Zerotorescue@80 | 194 | 
| Zerotorescue@80 | 195 -- Remember which tabs were scanned and don't scan them again | 
| Zerotorescue@80 | 196 local guildBankTabsScanned = {}; | 
| Zerotorescue@80 | 197 | 
| Zerotorescue@80 | 198 local function GUILDBANKFRAME_CLOSED() | 
| Zerotorescue@81 | 199 	addon:Debug("Scanner:GUILDBANKFRAME_CLOSED"); | 
| Zerotorescue@81 | 200 | 
| Zerotorescue@81 | 201 	table.wipe(guildBankTabsScanned); | 
| Zerotorescue@81 | 202 | 
| Zerotorescue@80 | 203 	mod:UnregisterEvent("GUILDBANKFRAME_CLOSED"); | 
| Zerotorescue@80 | 204 	mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED"); | 
| Zerotorescue@80 | 205 | 
| Zerotorescue@81 | 206 	StaticPopup_Hide("InventoriumRefill"); | 
| Zerotorescue@80 | 207 end | 
| Zerotorescue@80 | 208 | 
| Zerotorescue@80 | 209 local function GUILDBANKBAGSLOTS_CHANGED() | 
| Zerotorescue@80 | 210 	if not guildBankTabsScanned[GetCurrentGuildBankTab()] then | 
| Zerotorescue@81 | 211 		addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning"); | 
| Zerotorescue@81 | 212 | 
| Zerotorescue@80 | 213 		mod:Scan(addon.Locations.Guild); | 
| Zerotorescue@80 | 214 		guildBankTabsScanned[GetCurrentGuildBankTab()] = true; | 
| Zerotorescue@80 | 215 	else | 
| Zerotorescue@80 | 216 		addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning"); | 
| Zerotorescue@80 | 217 	end | 
| Zerotorescue@80 | 218 end | 
| Zerotorescue@80 | 219 | 
| Zerotorescue@80 | 220 local function GUILDBANKFRAME_OPENED() | 
| Zerotorescue@81 | 221 	addon:Debug("Scanner:GUILDBANKFRAME_OPENED"); | 
| Zerotorescue@81 | 222 | 
| Zerotorescue@80 | 223 	table.wipe(guildBankTabsScanned); | 
| Zerotorescue@80 | 224 | 
| Zerotorescue@80 | 225 	mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED); | 
| Zerotorescue@80 | 226 	mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED); | 
| Zerotorescue@80 | 227 end | 
| Zerotorescue@80 | 228 | 
| Zerotorescue@80 | 229 function mod:OnEnable() | 
| Zerotorescue@80 | 230 	-- Scan once when the bankframe is opened | 
| Zerotorescue@80 | 231 	mod:RegisterEvent("BANKFRAME_OPENED", BANKFRAME_OPENED); | 
| Zerotorescue@80 | 232 	mod:RegisterEvent("GUILDBANKFRAME_OPENED", GUILDBANKFRAME_OPENED); | 
| Zerotorescue@80 | 233 | 
| Zerotorescue@80 | 234 	Mover = addon:GetModule("Mover"); | 
| Zerotorescue@80 | 235 end | 
| Zerotorescue@80 | 236 | 
| Zerotorescue@80 | 237 function mod:OnDisable() | 
| Zerotorescue@80 | 238 	Mover = nil; | 
| Zerotorescue@80 | 239 | 
| Zerotorescue@80 | 240 	-- Bank | 
| Zerotorescue@80 | 241 	mod:UnregisterEvent("BANKFRAME_OPENED"); | 
| Zerotorescue@80 | 242 | 
| Zerotorescue@80 | 243 	-- Guild | 
| Zerotorescue@80 | 244 	GUILDBANKFRAME_CLOSED(); | 
| Zerotorescue@80 | 245 	mod:UnregisterEvent("GUILDBANKFRAME_OPENED"); | 
| Zerotorescue@80 | 246 end | 
| Zerotorescue@80 | 247 | 
| Zerotorescue@80 | 248 function mod:Pause() | 
| Zerotorescue@80 | 249 	paused = true; | 
| Zerotorescue@80 | 250 end | 
| Zerotorescue@80 | 251 | 
| Zerotorescue@80 | 252 function mod:Unpause() | 
| Zerotorescue@80 | 253 	paused = nil; | 
| Zerotorescue@80 | 254 end |