diff Scanner.lua @ 80:c0bf2ddb5288

Added initial item refilling from the bank/guild. Not yet fully functional.
author Zerotorescue
date Wed, 05 Jan 2011 13:05:15 +0100
parents
children 58617c7827fa
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scanner.lua	Wed Jan 05 13:05:15 2011 +0100
@@ -0,0 +1,236 @@
+local addon = select(2, ...);
+local mod = addon:NewModule("Scanner", "AceEvent-3.0");
+
+addon.Locations = {
+	Bag = 0,
+	Bank = 1,
+	Guild = 2,
+};
+
+local Mover, paused;
+local itemCache = {};
+
+local function _GetItemCount(itemId, location)
+	if location == addon.Locations.Bank then
+		-- No longer using GetItemCount as this includes equiped items and containers (e.g. bank bags)
+		--return (GetItemCount(itemId, true) - GetItemCount(itemId, false)); -- GetItemCount(X, true) provides count for bag+bank, GetItemCount(X, false) provides just bag, so (GetItemCount(X, true) - GetItemCount(X, false)) = just bank
+		return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
+	elseif location == addon.Locations.Guild then
+		return ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
+	else
+		error("Invalid location provided for the local _GetItemCount. Must be Bag or Bank.");
+	end
+end
+
+local function GetItemID(link)
+	return tonumber(link:match("|Hitem:([-0-9]+):"));
+end
+
+function mod:ClearCache()
+	table.wipe(itemCache);
+end
+
+function mod:CacheLocation(location, remember)
+	if location == addon.Locations.Bag or location == addon.Locations.Bank then
+		-- Reset cache just in case it was filled
+		self:ClearCache();
+		
+		local start, stop;
+		if location == addon.Locations.Bag then
+			start = 0;
+			stop = NUM_BAG_SLOTS;
+		else
+			-- If we requested the bank then we don't want the bag info
+			start = ( NUM_BAG_SLOTS + 1 );
+			stop = ( NUM_BAG_SLOTS + NUM_BANKBAGSLOTS );
+		end
+		
+		-- Go through all our bags, including the backpack
+		for i = start, ((addon.Locations.Bag and stop) or (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
+			-- Scan the default 100 slots whenever we're at a non-existing index
+			local bagId = (i == (stop + 1) and BANK_CONTAINER) or i;
+			local slotId = GetContainerNumSlots(bagId);
+			
+			while slotId ~= 0 do
+				-- A not equal-comparison should be quicker than a larger than-comparison
+				
+				local itemId = GetContainerItemID(bagId, slotId);
+				local itemCount = itemId and select(2, GetContainerItemInfo(bagId, slotId));
+				
+				if itemId and itemCount and itemCount > 0 then
+					local itemMove;
+					if not itemCache[itemId] then
+						-- If this is the first time we see this item, make a new object
+						itemMove = addon.ItemMove:New();
+					else
+						-- If we had this item in another slot too
+						itemMove = itemCache[itemId];
+					end
+					
+					itemMove.AddLocation(bagId, slotId, itemCount);
+				end
+			
+				-- Continue scanning a different slot
+				slotId = (slotId - 1);
+			end
+		end
+	elseif location == addon.Locations.Guild then
+		-- Reset cache before we scan
+		self:ClearCache();
+		
+		local tabId = GetCurrentGuildBankTab();
+		local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot
+		
+		if tabId == nil or tabId < 1 then return; end
+		
+		while slotId ~= 0 do
+			-- A not equal-comparison should be quicker than a larger than-comparison
+			
+				-- If there is actually an item in this slot
+				
+			local itemLink = GetGuildBankItemLink(tabId, slotId);
+			local itemId = itemLink and GetItemId(itemLink);
+			local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId));
+				
+			if itemLink and itemId and itemCount and itemCount > 0 then
+				local itemMove;
+				if not itemCache[itemId] then
+					-- If this is the first time we see this item, make a new object
+					itemMove = addon.ItemMove:New();
+				else
+					-- If we had this item in another slot too
+					itemMove = itemCache[itemId];
+				end
+				
+				itemMove.AddLocation(tabId, slotId, itemCount);
+			end
+			
+			-- Continue scanning a different slot
+			slotId = (slotId - 1);
+		end
+	else
+		error("Invalid location provided for the local _GetItemCount. Must be Bank or Guild.");
+	end
+	
+	if not remember then
+		-- Copy the table as clearing the cache wipes it empty (and tables are passed by reference)
+		local cacheCopy = CopyTable(itemCache);
+		
+		self:ClearCache();
+		
+		return cacheCopy;
+	end
+end
+
+function mod:Scan(location)
+	-- We might pause the scanning when we invoke moves ourself
+	if paused then
+		return;
+	end
+	
+	local playerName = UnitName("player");
+	
+	self:CacheLocation(location, true);
+	
+	-- Go through all groups
+	for groupName, values in pairs(addon.db.profile.groups) do
+		local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters");
+		
+		if values.items and trackAt[playerName] then
+			-- Is this character interested in this data?
+			
+			local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock");
+			
+			-- Go through all items
+			for itemId, _ in pairs(values.items) do
+				
+				-- Check if we have enough items local
+				local missingItems = (minLocalStock - addon:GetLocalItemCount(itemId, groupName));
+				
+				if missingItems > 0 then
+					-- Check how many are available
+					local availableItems = _GetItemCount(itemId, location);
+					
+					if availableItems > 0 then
+						print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")");
+						
+						Mover:AddMove(itemId, missingItems);
+					else
+						print("Insufficient " .. select(2, GetItemInfo(itemId)));
+					end
+				end
+			end
+		end
+	end
+	
+	self:ClearCache();
+	
+	self:Pause();
+	Mover:BeginMove(location, self.Unpause);
+end
+
+local function BANKFRAME_OPENED()
+	-- Scan once when the bank is opened, but no need to scan after
+	mod:Scan(addon.Locations.Bank);
+	
+	addon:Debug("Scanner:BANKFRAME_OPENED");
+end
+
+-- Remember which tabs were scanned and don't scan them again
+local guildBankTabsScanned = {};
+
+local function GUILDBANKFRAME_CLOSED()
+	mod:UnregisterEvent("GUILDBANKFRAME_CLOSED");
+	mod:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED");
+	
+	table.wipe(guildBankTabsScanned);
+	
+	addon:Debug("Scanner:GUILDBANKFRAME_CLOSED");
+end
+
+local function GUILDBANKBAGSLOTS_CHANGED()
+	if not guildBankTabsScanned[GetCurrentGuildBankTab()] then
+		mod:Scan(addon.Locations.Guild);
+		guildBankTabsScanned[GetCurrentGuildBankTab()] = true;
+		
+		addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - scanning");
+	else
+		addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED (" .. GetCurrentGuildBankTab() .. ") - not scanning");
+	end
+end
+
+local function GUILDBANKFRAME_OPENED()
+	table.wipe(guildBankTabsScanned);
+	
+	mod:RegisterEvent("GUILDBANKFRAME_CLOSED", GUILDBANKFRAME_CLOSED);
+	mod:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", GUILDBANKBAGSLOTS_CHANGED);
+	
+	addon:Debug("Scanner:GUILDBANKFRAME_OPENED");
+end
+
+function mod:OnEnable()
+	-- Scan once when the bankframe is opened
+	mod:RegisterEvent("BANKFRAME_OPENED", BANKFRAME_OPENED);
+	mod:RegisterEvent("GUILDBANKFRAME_OPENED", GUILDBANKFRAME_OPENED);
+	
+	Mover = addon:GetModule("Mover");
+end
+
+function mod:OnDisable()
+	Mover = nil;
+	
+	-- Bank
+	mod:UnregisterEvent("BANKFRAME_OPENED");
+	
+	-- Guild
+	GUILDBANKFRAME_CLOSED();
+	mod:UnregisterEvent("GUILDBANKFRAME_OPENED");
+end
+
+function mod:Pause()
+	paused = true;
+end
+
+function mod:Unpause()
+	paused = nil;
+end