diff Modules/Scanner.lua @ 84:3bec0ea44607

Cleaned the Inventorium folder; moved all classes to classes directory, modules to modules directory and support addons to plugins directory. In addition support addons are now references within XML files rather than inside the TOC. Fixed the default local item count setting, you can now exclude bag and AH data from it. Fixed some mover algorithm bugs. Mover can no longer freeze the game but instead will terminate the process after a 1000 passes. Now reversing the moves table after making it, rather than every single time it is used. Fixed guild bank support. Now displaying the amount of items moved. Scanner now scans all guild bank tabs rather than only the current. Fixed a bug with local item data not being retrieved properly. Disabled ?enterClicksFirstButton? within dialogs as this causes the dialog to consume all keypress. Events are now at the addon object rather than local.
author Zerotorescue
date Thu, 06 Jan 2011 20:05:30 +0100
parents Scanner.lua@f885805da5d6
children a12d22ef3f39
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Modules/Scanner.lua	Thu Jan 06 20:05:30 2011 +0100
@@ -0,0 +1,274 @@
+local addon = select(2, ...);
+local mod = addon:NewModule("Scanner", "AceEvent-3.0", "AceTimer-3.0");
+
+addon.Locations = {
+	Bag = 0,
+	Bank = 1,
+	Guild = 2,
+};
+
+local Mover, paused;
+local itemCache = {};
+
+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, ((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
+			-- 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.ContainerItem:New();
+						itemCache[itemId] = itemMove;
+					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();
+		
+		for tabId = 1, GetNumGuildBankTabs() do
+			local isViewable = select(3, GetGuildBankTabInfo(tabId));
+			
+			if isViewable == 1 then
+				local slotId = (MAX_GUILDBANK_SLOTS_PER_TAB or 98); -- start by scanning the last slot
+				
+				while slotId ~= 0 do
+					-- A not equal-comparison should be quicker than a larger than-comparison
+					
+					local itemLink = GetGuildBankItemLink(tabId, slotId);
+					local itemId = itemLink and addon:GetItemID(itemLink);
+					local itemCount = itemLink and select(2, GetGuildBankItemInfo(tabId, slotId));
+						
+					if itemLink and itemId and itemCount and itemCount > 0 then
+						-- If there is actually an item in this slot
+						local itemMove;
+						if not itemCache[itemId] then
+							-- If this is the first time we see this item, make a new object
+							itemMove = addon.ContainerItem:New();
+							itemCache[itemId] = itemMove;
+						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
+			end
+		end
+	else
+		error("Invalid location provided for CacheLocation. 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");
+		local localItemData = addon:GetOptionByKey(groupName, "localItemData");
+		
+		if values.items and trackAt[playerName] and addon:GetOptionByKey(groupName, "autoRefill") and (location ~= addon.Locations.Bank or not localItemData or not localItemData["Bank"]) 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 (but only do so if this location also has enough available)
+				local missingItems = itemCache[itemId] and (minLocalStock - addon:GetLocalItemCount(itemId, groupName));
+				
+				if itemCache[itemId] and missingItems > 0 then
+					-- Check how many are available
+					local availableItems = ((itemCache[itemId] and itemCache[itemId].totalCount) or 0);
+					
+					if availableItems > 0 then
+						print("Insufficient " .. select(2, GetItemInfo(itemId)) .. " but this location has " .. availableItems .. " (moving " .. missingItems .. ")");
+						
+						Mover:AddMove(itemId, missingItems);
+					else
+						print("Insufficient " .. IdToItemLink(itemId));
+					end
+				end
+			end
+		end
+	end
+	
+	self:ClearCache();
+	
+	if Mover:HasMoves() then
+		StaticPopupDialogs["InventoriumRefill"] = {
+			text = "There are items that can be refilled from this location, do you wish to proceed?",
+			button1 = YES,
+			button2 = NO,
+			OnAccept = function()
+				mod:Pause();
+				Mover:BeginMove(location, self.Unpause);
+			end,
+			timeout = 0,
+			whileDead = 1,
+			hideOnEscape = 1,
+			exclusive = 1,
+		};
+		StaticPopup_Show("InventoriumRefill");
+	end
+end
+
+
+
+-- Events
+
+-- Player bank
+
+function mod:BANKFRAME_OPENED()
+	addon:Debug("Scanner:BANKFRAME_OPENED");
+	
+	mod:RegisterEvent("BANKFRAME_CLOSED");
+	
+	-- Scan once when the bank is opened, but no need to scan after
+	mod:Scan(addon.Locations.Bank);
+end
+
+function mod:BANKFRAME_CLOSED()
+	addon:Debug("Scanner:BANKFRAME_CLOSED");
+	
+	mod:UnregisterEvent("BANKFRAME_CLOSED");
+	
+	StaticPopup_Hide("InventoriumRefill");
+end
+
+-- Guild bank
+
+local tmrScanGuild, scanned;
+function mod:GUILDBANKBAGSLOTS_CHANGED()
+	-- This event is spammed the first time the guild bank is opened
+	if not scanned then
+		self:CancelTimer(tmrScanGuild, true); -- silent
+		tmrScanGuild = self:ScheduleTimer("DoScanGuild", 1);
+	end
+end
+
+function mod:DoScanGuild()
+	if not scanned then
+		addon:Debug("Scanner:GUILDBANKBAGSLOTS_CHANGED");
+		
+		scanned = true;
+		
+		self:Scan(addon.Locations.Guild);
+	end
+end
+
+function mod:GUILDBANKFRAME_CLOSED()
+	addon:Debug("Scanner:GUILDBANKFRAME_CLOSED");
+	
+	scanned = nil;
+	
+	self:UnregisterEvent("GUILDBANKFRAME_CLOSED");
+	self:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED");
+	
+	self:CancelTimer(tmrScanGuild, true); -- silent
+	
+	StaticPopup_Hide("InventoriumRefill");
+end
+
+function mod:GUILDBANKFRAME_OPENED()
+	addon:Debug("Scanner:GUILDBANKFRAME_OPENED");
+	
+	scanned = nil;
+	
+	-- Get the contents for every tab into our cache
+	for tabId = 1, GetNumGuildBankTabs() do
+		local isViewable = select(3, GetGuildBankTabInfo(tabId));
+		if isViewable == 1 then		
+			QueryGuildBankTab(tabId);
+		end
+	end
+	
+	self:RegisterEvent("GUILDBANKFRAME_CLOSED");
+	self:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED");
+end
+
+function mod:OnEnable()
+	-- Scan once when the bankframe is opened
+	self:RegisterEvent("BANKFRAME_OPENED");
+	self:RegisterEvent("GUILDBANKFRAME_OPENED");
+	
+	Mover = addon:GetModule("Mover");
+end
+
+function mod:OnDisable()
+	Mover = nil;
+	
+	-- Bank
+	self:UnregisterEvent("BANKFRAME_OPENED");
+	
+	-- Guild
+	self:GUILDBANKFRAME_CLOSED();
+	self:UnregisterEvent("GUILDBANKFRAME_OPENED");
+end
+
+function mod:Pause()
+	paused = true;
+end
+
+function mod:Unpause()
+	paused = nil;
+end