| Zerotorescue@80 | 1 local addon = select(2, ...); | 
| Zerotorescue@80 | 2 local mod = addon:NewModule("Mover", "AceEvent-3.0", "AceTimer-3.0"); | 
| Zerotorescue@80 | 3 | 
| Zerotorescue@80 | 4 local Scanner; | 
| Zerotorescue@80 | 5 local queuedMoves = {}; -- table storing all queued moves before BeginMove is called | 
| Zerotorescue@80 | 6 local combinedMoves = {}; -- table storing all combined moves (with source and target) that is to be processed by the actual mover in the order of the index (1 to #) | 
| Zerotorescue@81 | 7 local movesSource; | 
| Zerotorescue@80 | 8 | 
| Zerotorescue@80 | 9 function mod:AddMove(itemId, amount) | 
| Zerotorescue@80 | 10 	table.insert(queuedMoves, { | 
| Zerotorescue@80 | 11 		id = itemId, | 
| Zerotorescue@80 | 12 		num = amount, | 
| Zerotorescue@80 | 13 	}); | 
| Zerotorescue@80 | 14 end | 
| Zerotorescue@80 | 15 | 
| Zerotorescue@81 | 16 function mod:HasMoves() | 
| Zerotorescue@81 | 17 	return (#queuedMoves ~= 0); | 
| Zerotorescue@81 | 18 end | 
| Zerotorescue@81 | 19 | 
| Zerotorescue@80 | 20 function mod:BeginMove(location, onFinish) | 
| Zerotorescue@81 | 21 	addon:Debug("BeginMove"); | 
| Zerotorescue@80 | 22 | 
| Zerotorescue@80 | 23 	-- Find the outgoing moves | 
| Zerotorescue@80 | 24 	-- We need the source container and slot, find all the requires sources and put them in a list which we go through later to find matching targets | 
| Zerotorescue@80 | 25 | 
| Zerotorescue@80 | 26 	-- Get a list of items in the source container | 
| Zerotorescue@80 | 27 	local sourceContents = Scanner:CacheLocation(location, false); | 
| Zerotorescue@80 | 28 | 
| Zerotorescue@80 | 29 	local outgoingMoves = {}; | 
| Zerotorescue@80 | 30 | 
| Zerotorescue@81 | 31 	for _, singleMove in pairs(queuedMoves) do | 
| Zerotorescue@80 | 32 		local sourceItem = sourceContents[singleMove.id]; | 
| Zerotorescue@80 | 33 		if not sourceItem then | 
| Zerotorescue@80 | 34 			print("Can't move " .. IdToItemLink(singleMove.id) .. ", non-existant in source"); | 
| Zerotorescue@80 | 35 		else | 
| Zerotorescue@80 | 36 			-- We want to move the smallest stacks first to keep stuff pretty | 
| Zerotorescue@80 | 37 			table.sort(sourceItem.locations, function(a, b) | 
| Zerotorescue@81 | 38 				return a.count < b.count; | 
| Zerotorescue@80 | 39 			end); | 
| Zerotorescue@80 | 40 | 
| Zerotorescue@81 | 41 			for _, itemLocation in pairs(sourceItem.locations) do | 
| Zerotorescue@80 | 42 				-- if this location has more items than we need, only move what we need, otherwise move everything in this stack | 
| Zerotorescue@80 | 43 				local movingNum = ((itemLocation.count > singleMove.num and singleMove.num) or itemLocation.count); | 
| Zerotorescue@80 | 44 | 
| Zerotorescue@80 | 45 				table.insert(outgoingMoves, { | 
| Zerotorescue@80 | 46 					itemId = singleMove.id, | 
| Zerotorescue@80 | 47 					container = itemLocation.container, | 
| Zerotorescue@80 | 48 					slot = itemLocation.slot, | 
| Zerotorescue@80 | 49 					count = movingNum, | 
| Zerotorescue@80 | 50 				}); | 
| Zerotorescue@80 | 51 | 
| Zerotorescue@80 | 52 				singleMove.num = (singleMove.num - movingNum); | 
| Zerotorescue@80 | 53 | 
| Zerotorescue@80 | 54 				if singleMove.num == 0 then | 
| Zerotorescue@80 | 55 					-- If we have prepared everything we wanted, go to the next queued move | 
| Zerotorescue@81 | 56 					break; -- stop the locations-loop | 
| Zerotorescue@80 | 57 				end | 
| Zerotorescue@80 | 58 			end | 
| Zerotorescue@80 | 59 		end | 
| Zerotorescue@80 | 60 	end | 
| Zerotorescue@80 | 61 | 
| Zerotorescue@80 | 62 	-- No longer needed | 
| Zerotorescue@80 | 63 	table.wipe(queuedMoves); | 
| Zerotorescue@80 | 64 | 
| Zerotorescue@80 | 65 	-- Process every single outgoing move and find fitting targets | 
| Zerotorescue@80 | 66 | 
| Zerotorescue@80 | 67 	-- Get a list of items already in the target container | 
| Zerotorescue@80 | 68 	local targetContents = Scanner:CacheLocation(addon.Locations.Bag, false); | 
| Zerotorescue@80 | 69 | 
| Zerotorescue@80 | 70 	-- Find all empty slots | 
| Zerotorescue@80 | 71 | 
| Zerotorescue@80 | 72 	local emptySlots = {}; | 
| Zerotorescue@80 | 73 | 
| Zerotorescue@80 | 74 	local start = 0; | 
| Zerotorescue@80 | 75 	local stop = NUM_BAG_SLOTS; | 
| Zerotorescue@80 | 76 | 
| Zerotorescue@80 | 77 	-- Go through all our bags, including the backpack | 
| Zerotorescue@80 | 78 	for bagId = start, stop do | 
| Zerotorescue@80 | 79 		-- Go through all our slots | 
| Zerotorescue@80 | 80 		for slotId = 1, GetContainerNumSlots(bagId) do | 
| Zerotorescue@80 | 81 			local itemId = GetContainerItemID(bagId, slotId); | 
| Zerotorescue@80 | 82 | 
| Zerotorescue@80 | 83 			if not itemId then | 
| Zerotorescue@80 | 84 				table.insert(emptySlots, { | 
| Zerotorescue@81 | 85 					container = bagId, | 
| Zerotorescue@81 | 86 					slot = slotId, | 
| Zerotorescue@80 | 87 				}); | 
| Zerotorescue@80 | 88 			end | 
| Zerotorescue@80 | 89 		end | 
| Zerotorescue@80 | 90 	end | 
| Zerotorescue@80 | 91 | 
| Zerotorescue@81 | 92 	-- Remember where we're moving from | 
| Zerotorescue@81 | 93 	movesSource = location; | 
| Zerotorescue@81 | 94 | 
| Zerotorescue@80 | 95 	while #outgoingMoves ~= 0 do | 
| Zerotorescue@80 | 96 		-- A not equal-comparison should be quicker than a larger/smaller than-comparison | 
| Zerotorescue@80 | 97 | 
| Zerotorescue@81 | 98 		for _, outgoingMove in pairs(outgoingMoves) do | 
| Zerotorescue@80 | 99 			-- itemId  will be set to nil when this outgoing move was processed - sanity check | 
| Zerotorescue@80 | 100 			if outgoingMove.itemId then | 
| Zerotorescue@80 | 101 				local targetItem = targetContents[outgoingMove.itemId]; | 
| Zerotorescue@80 | 102 | 
| Zerotorescue@80 | 103 				if not targetItem then | 
| Zerotorescue@80 | 104 					-- grab an empty slot | 
| Zerotorescue@80 | 105 					-- make new instance of ItemMove | 
| Zerotorescue@80 | 106 					-- populate targetContents with it so future moves of this item can be put on top of it if this isn't a full stack | 
| Zerotorescue@80 | 107 | 
| Zerotorescue@80 | 108 					local firstAvailableSlot = emptySlots[1]; | 
| Zerotorescue@80 | 109 | 
| Zerotorescue@80 | 110 					if not firstAvailableSlot then | 
| Zerotorescue@80 | 111 						print("Bags are full. Skipping " .. IdToItemLink(outgoingMove.itemId) .. "."); | 
| Zerotorescue@80 | 112 | 
| Zerotorescue@80 | 113 						outgoingMove.itemId = nil; | 
| Zerotorescue@80 | 114 					else | 
| Zerotorescue@80 | 115 						table.insert(combinedMoves, { | 
| Zerotorescue@80 | 116 							sourceContainer = outgoingMove.container, | 
| Zerotorescue@80 | 117 							sourceSlot = outgoingMove.slot, | 
| Zerotorescue@80 | 118 							targetContainer = firstAvailableSlot.container, | 
| Zerotorescue@80 | 119 							targetSlot = firstAvailableSlot.slot, | 
| Zerotorescue@80 | 120 							itemId = outgoingMove.itemId, | 
| Zerotorescue@80 | 121 							num = outgoingMove.count, | 
| Zerotorescue@80 | 122 						}); | 
| Zerotorescue@80 | 123 | 
| Zerotorescue@80 | 124 						-- We filled an empty slot so the target contents now has one more item, | 
| Zerotorescue@80 | 125 						-- make a new instance of the ItemMove class so any additional items with this id can be stacked on top of it | 
| Zerotorescue@81 | 126 						local itemMove = addon.ContainerItem:New(); | 
| Zerotorescue@81 | 127 						itemMove:AddLocation(firstAvailableSlot.container, firstAvailableSlot.slot, outgoingMove.count); | 
| Zerotorescue@80 | 128 						targetContents[outgoingMove.itemId] = itemMove; | 
| Zerotorescue@80 | 129 | 
| Zerotorescue@81 | 130 						table.remove(emptySlots, 1); -- no longer empty | 
| Zerotorescue@80 | 131 | 
| Zerotorescue@80 | 132 						outgoingMove.count = 0; -- nothing remaining - sanity check | 
| Zerotorescue@80 | 133 						outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table | 
| Zerotorescue@80 | 134 					end | 
| Zerotorescue@80 | 135 				else | 
| Zerotorescue@80 | 136 					-- Find the maximum stack size for this item | 
| Zerotorescue@80 | 137 					local itemStackCount = select(8, GetItemInfo(outgoingMove.itemId)); | 
| Zerotorescue@80 | 138 | 
| Zerotorescue@80 | 139 					-- We want to move to the largest stacks first to keep stuff pretty | 
| Zerotorescue@80 | 140 					table.sort(targetItem.locations, function(a, b) | 
| Zerotorescue@81 | 141 						return a.count > b.count; | 
| Zerotorescue@80 | 142 					end); | 
| Zerotorescue@80 | 143 | 
| Zerotorescue@81 | 144 					for _, itemLocation in pairs(targetItem.locations) do | 
| Zerotorescue@80 | 145 						if itemLocation.count < itemStackCount and outgoingMove.count > 0 then | 
| Zerotorescue@80 | 146 							-- Check if this stack isn't already full (and we still need to move this item) | 
| Zerotorescue@80 | 147 | 
| Zerotorescue@80 | 148 							local remainingSpace = (itemStackCount - itemLocation.count); | 
| Zerotorescue@80 | 149 							if remainingSpace > outgoingMove.count then | 
| Zerotorescue@80 | 150 								-- Enough room to move this entire stack | 
| Zerotorescue@80 | 151 								-- Deposit this item and then forget this outgoing move as everything in it was processed | 
| Zerotorescue@80 | 152 | 
| Zerotorescue@80 | 153 								table.insert(combinedMoves, { | 
| Zerotorescue@80 | 154 									sourceContainer = outgoingMove.container, | 
| Zerotorescue@80 | 155 									sourceSlot = outgoingMove.slot, | 
| Zerotorescue@80 | 156 									targetContainer = itemLocation.container, | 
| Zerotorescue@80 | 157 									targetSlot = itemLocation.slot, | 
| Zerotorescue@80 | 158 									itemId = outgoingMove.itemId, | 
| Zerotorescue@80 | 159 									num = outgoingMove.count, | 
| Zerotorescue@80 | 160 								}); | 
| Zerotorescue@80 | 161 | 
| Zerotorescue@80 | 162 								itemLocation.count = (itemLocation.count + outgoingMove.count); | 
| Zerotorescue@80 | 163 								outgoingMove.count = 0; -- nothing remaining | 
| Zerotorescue@80 | 164 								outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table | 
| Zerotorescue@80 | 165 								break; -- stop the locations-loop | 
| Zerotorescue@80 | 166 							else | 
| Zerotorescue@80 | 167 								-- Deposit this item but don't remove the outgoing move as there are some items left to move | 
| Zerotorescue@80 | 168 | 
| Zerotorescue@80 | 169 								table.insert(combinedMoves, { | 
| Zerotorescue@80 | 170 									sourceContainer = outgoingMove.container, | 
| Zerotorescue@80 | 171 									sourceSlot = outgoingMove.slot, | 
| Zerotorescue@80 | 172 									targetContainer = itemLocation.container, | 
| Zerotorescue@80 | 173 									targetSlot = itemLocation.slot, | 
| Zerotorescue@80 | 174 									itemId = outgoingMove.itemId, | 
| Zerotorescue@80 | 175 									num = outgoingMove.count, | 
| Zerotorescue@80 | 176 								}); | 
| Zerotorescue@80 | 177 | 
| Zerotorescue@80 | 178 								-- The target will be full when we complete, but the source will still have remaining items left to be moved | 
| Zerotorescue@80 | 179 								itemLocation.count = itemStackCount; | 
| Zerotorescue@80 | 180 								outgoingMove.count = (outgoingMove.count - remainingSpace); | 
| Zerotorescue@80 | 181 							end | 
| Zerotorescue@80 | 182 						end | 
| Zerotorescue@80 | 183 					end | 
| Zerotorescue@80 | 184 | 
| Zerotorescue@80 | 185 					if outgoingMove.count > 0 then | 
| Zerotorescue@80 | 186 						-- We went through all matching items and checked their stack sizes if we could move this there, no room available | 
| Zerotorescue@80 | 187 						-- So forget about the target item (even though it may just have full locations, these are useless anyway) and the next loop move it onto an empty slot | 
| Zerotorescue@80 | 188 						targetItem = nil; | 
| Zerotorescue@80 | 189 					end | 
| Zerotorescue@80 | 190 				end | 
| Zerotorescue@80 | 191 			end | 
| Zerotorescue@80 | 192 		end | 
| Zerotorescue@80 | 193 | 
| Zerotorescue@80 | 194 		-- Loop through the array to find items that should be removed, start with the last element or the loop would break | 
| Zerotorescue@80 | 195 		local numOutgoingMoves = #outgoingMoves; -- since LUA-tables start at an index of 1, this is actually an existing index (outgoingMoves[#outgoingMoves] would return a value) | 
| Zerotorescue@80 | 196 		while numOutgoingMoves ~= 0 do | 
| Zerotorescue@80 | 197 			-- A not equal-comparison should be quicker than a larger/smaller than-comparison | 
| Zerotorescue@80 | 198 | 
| Zerotorescue@80 | 199 			-- Check if the item id is nil, this is set to nil when this outgoing move has been processed | 
| Zerotorescue@80 | 200 			if not outgoingMoves[numOutgoingMoves].itemId then | 
| Zerotorescue@80 | 201 				-- Remove this element from the array | 
| Zerotorescue@80 | 202 				table.remove(outgoingMoves, numOutgoingMoves); | 
| Zerotorescue@80 | 203 			end | 
| Zerotorescue@80 | 204 | 
| Zerotorescue@80 | 205 			-- Proceed with the next element (or previous considering we're going from last to first) | 
| Zerotorescue@80 | 206 			numOutgoingMoves = (numOutgoingMoves - 1); | 
| Zerotorescue@80 | 207 		end | 
| Zerotorescue@80 | 208 	end | 
| Zerotorescue@80 | 209 | 
| Zerotorescue@80 | 210 	-- No longer needed | 
| Zerotorescue@80 | 211 	table.wipe(emptySlots); | 
| Zerotorescue@80 | 212 | 
| Zerotorescue@81 | 213 	self:ProcessMove(); | 
| Zerotorescue@80 | 214 | 
| Zerotorescue@81 | 215 	self:RegisterEvent("BAG_UPDATE"); | 
| Zerotorescue@80 | 216 | 
| Zerotorescue@81 | 217 	onFinish(); | 
| Zerotorescue@80 | 218 end | 
| Zerotorescue@80 | 219 | 
| Zerotorescue@81 | 220 if not table.reverse then | 
| Zerotorescue@81 | 221 -- 	table.reverse = function(orig) | 
| Zerotorescue@81 | 222 -- 		local temp = CopyTable(orig); | 
| Zerotorescue@81 | 223 -- 		local origLength = #temp; | 
| Zerotorescue@81 | 224 -- 		for i = 1, origLength do | 
| Zerotorescue@81 | 225 -- 			orig[(origLength - i + 1)] = temp[i]; | 
| Zerotorescue@81 | 226 -- 		end | 
| Zerotorescue@81 | 227 -- 	end | 
| Zerotorescue@81 | 228 	table.reverse = function(orig) | 
| Zerotorescue@81 | 229 		local temp = {}; | 
| Zerotorescue@81 | 230 		local origLength = #orig; | 
| Zerotorescue@81 | 231 		for i = 1, origLength do | 
| Zerotorescue@81 | 232 			temp[(origLength - i + 1)] = orig[i]; | 
| Zerotorescue@81 | 233 		end | 
| Zerotorescue@81 | 234 | 
| Zerotorescue@81 | 235 -- 		-- Update the original table (can't do orig = temp as that would change the reference-link instead of the original table) | 
| Zerotorescue@81 | 236 -- 		for i, v in pairs(temp) do | 
| Zerotorescue@81 | 237 -- 			orig[i] = v; | 
| Zerotorescue@81 | 238 -- 		end | 
| Zerotorescue@81 | 239 		return temp; -- for speed we choose to do a return instead | 
| Zerotorescue@81 | 240 	end | 
| Zerotorescue@81 | 241 end | 
| Zerotorescue@81 | 242 | 
| Zerotorescue@81 | 243 function mod:ProcessMove() | 
| Zerotorescue@81 | 244 	addon:Debug("ProcessMove"); | 
| Zerotorescue@81 | 245 | 
| Zerotorescue@81 | 246 	if #combinedMoves == 0 then | 
| Zerotorescue@81 | 247 		print("Nothing to move."); | 
| Zerotorescue@81 | 248 | 
| Zerotorescue@81 | 249 		self:Abort(); | 
| Zerotorescue@81 | 250 | 
| Zerotorescue@81 | 251 		return; | 
| Zerotorescue@81 | 252 	end | 
| Zerotorescue@81 | 253 | 
| Zerotorescue@81 | 254 	self:RegisterEvent("UI_ERROR_MESSAGE"); | 
| Zerotorescue@81 | 255 | 
| Zerotorescue@80 | 256 	-- combinedMoves now has all moves in it (source -> target) | 
| Zerotorescue@80 | 257 	-- go through list, move everything inside it | 
| Zerotorescue@81 | 258 	-- add source and target to lists, if either is already in this list, skip the move | 
| Zerotorescue@81 | 259 	-- repeat every few seconds until we're completely done | 
| Zerotorescue@80 | 260 | 
| Zerotorescue@80 | 261 	local sourceLocationsLocked = {}; | 
| Zerotorescue@80 | 262 	local targetLocationsLocked = {}; | 
| Zerotorescue@80 | 263 | 
| Zerotorescue@81 | 264 	-- Reverse table, we need to go through it from last to first because we'll be removing elements, but we don't want the actions to be executed in a different order | 
| Zerotorescue@81 | 265     combinedMoves = table.reverse(combinedMoves); | 
| Zerotorescue@81 | 266 | 
| Zerotorescue@80 | 267 	local numCurrentMove = #combinedMoves; | 
| Zerotorescue@80 | 268 	while numCurrentMove ~= 0 do | 
| Zerotorescue@80 | 269 		local move = combinedMoves[numCurrentMove]; | 
| Zerotorescue@80 | 270 | 
| Zerotorescue@80 | 271 		-- sourceContainer, sourceSlot, targetContainer, targetSlot, itemId, num | 
| Zerotorescue@81 | 272 		if move and (not sourceLocationsLocked[move.sourceContainer] or not sourceLocationsLocked[move.sourceContainer][move.sourceSlot]) and | 
| Zerotorescue@80 | 273 			(not targetLocationsLocked[move.targetContainer] or not targetLocationsLocked[move.targetContainer][move.targetSlot]) then | 
| Zerotorescue@80 | 274 | 
| Zerotorescue@80 | 275 			print("Moving " .. IdToItemLink(move.itemId)); | 
| Zerotorescue@80 | 276 | 
| Zerotorescue@81 | 277 			addon:Debug(("Moving %dx%s from (%d,%d) to (%d,%d)"):format(move.num, IdToItemLink(move.itemId), move.sourceContainer, move.sourceSlot, move.targetContainer, move.targetSlot)); | 
| Zerotorescue@81 | 278 | 
| Zerotorescue@81 | 279 			if GetContainerItemID(move.sourceContainer, move.sourceSlot) ~= move.itemId then | 
| Zerotorescue@81 | 280 				self:Abort("source changed", "Source (" .. move.sourceContainer .. "," .. move.sourceSlot .. ") is not " .. IdToItemLink(move.itemId)); | 
| Zerotorescue@81 | 281 | 
| Zerotorescue@81 | 282 				return; | 
| Zerotorescue@81 | 283 			end | 
| Zerotorescue@81 | 284 | 
| Zerotorescue@80 | 285 			-- Pickup stack | 
| Zerotorescue@81 | 286 			if movesSource == addon.Locations.Bank then | 
| Zerotorescue@81 | 287 				SplitContainerItem(move.sourceContainer, move.sourceSlot, move.num); | 
| Zerotorescue@81 | 288 			elseif movesSource == addon.Locations.Guild then | 
| Zerotorescue@81 | 289 				SplitGuildBankItem(move.sourceContainer, move.sourceSlot, move.num); | 
| Zerotorescue@81 | 290 			end | 
| Zerotorescue@80 | 291 | 
| Zerotorescue@80 | 292 			-- Remember we picked this item up and thus it is now locked | 
| Zerotorescue@80 | 293 			if not sourceLocationsLocked[move.sourceContainer] then | 
| Zerotorescue@80 | 294 				sourceLocationsLocked[move.sourceContainer] = {}; | 
| Zerotorescue@80 | 295 			end | 
| Zerotorescue@80 | 296 			sourceLocationsLocked[move.sourceContainer][move.sourceSlot] = true; | 
| Zerotorescue@80 | 297 | 
| Zerotorescue@81 | 298 			if movesSource == addon.Locations.Guild or CursorHasItem() then -- CursorHasItem is always false if source is a guild tab | 
| Zerotorescue@81 | 299 				if GetContainerItemID(move.targetContainer, move.targetSlot) and GetContainerItemID(move.targetContainer, move.targetSlot) ~= move.itemId then | 
| Zerotorescue@81 | 300 					self:Abort("target changed", "Target (" .. move.targetContainer .. "," .. move.targetSlot .. ") is not " .. IdToItemLink(move.itemId) .. " nor empty"); | 
| Zerotorescue@81 | 301 					return; | 
| Zerotorescue@81 | 302 				end | 
| Zerotorescue@81 | 303 | 
| Zerotorescue@80 | 304 				-- And drop it | 
| Zerotorescue@80 | 305 				PickupContainerItem(move.targetContainer, move.targetSlot); | 
| Zerotorescue@80 | 306 | 
| Zerotorescue@80 | 307 				-- Remember we dropped an item here and thus this is now locked | 
| Zerotorescue@81 | 308 				if not targetLocationsLocked[move.targetContainer] then | 
| Zerotorescue@81 | 309 					targetLocationsLocked[move.targetContainer] = {}; | 
| Zerotorescue@80 | 310 				end | 
| Zerotorescue@81 | 311 				targetLocationsLocked[move.targetContainer][move.targetSlot] = true; | 
| Zerotorescue@80 | 312 | 
| Zerotorescue@80 | 313 				-- This move was processed | 
| Zerotorescue@80 | 314 				table.remove(combinedMoves, numCurrentMove); | 
| Zerotorescue@81 | 315 			else | 
| Zerotorescue@81 | 316 				self:Abort("item disappeared from mouse", "Couldn't move " .. IdToItemLink(move.itemId) .. ", CursorHasItem() is false"); | 
| Zerotorescue@81 | 317 				return; | 
| Zerotorescue@80 | 318 			end | 
| Zerotorescue@80 | 319 		end | 
| Zerotorescue@80 | 320 | 
| Zerotorescue@80 | 321 		-- Proceed with the next element (or previous considering we're going from last to first) | 
| Zerotorescue@80 | 322 		numCurrentMove = (numCurrentMove - 1); | 
| Zerotorescue@80 | 323 	end | 
| Zerotorescue@81 | 324 | 
| Zerotorescue@81 | 325 	if #combinedMoves == 0 then | 
| Zerotorescue@81 | 326 		print("Finished."); | 
| Zerotorescue@81 | 327 | 
| Zerotorescue@81 | 328 		self:Abort(); | 
| Zerotorescue@81 | 329 | 
| Zerotorescue@81 | 330 		return; | 
| Zerotorescue@81 | 331 	end | 
| Zerotorescue@80 | 332 end | 
| Zerotorescue@80 | 333 | 
| Zerotorescue@80 | 334 local tmrProcessNext; | 
| Zerotorescue@81 | 335 function mod:BAG_UPDATE() | 
| Zerotorescue@81 | 336 	self:CancelTimer(tmrProcessNext, true); -- silent | 
| Zerotorescue@81 | 337 	tmrProcessNext = self:ScheduleTimer("ProcessMove", 1); | 
| Zerotorescue@80 | 338 end | 
| Zerotorescue@80 | 339 | 
| Zerotorescue@81 | 340 function IdToItemLink(itemId) | 
| Zerotorescue@81 | 341 	local itemLink = select(2, GetItemInfo(itemId)); | 
| Zerotorescue@81 | 342 	itemLink = itemLink or "Unknown (" .. itemId .. ")"; | 
| Zerotorescue@81 | 343 	return itemLink; | 
| Zerotorescue@81 | 344 end | 
| Zerotorescue@81 | 345 | 
| Zerotorescue@81 | 346 function mod:UI_ERROR_MESSAGE(e, errorMessage) | 
| Zerotorescue@81 | 347 	if errorMessage == ERR_SPLIT_FAILED then | 
| Zerotorescue@81 | 348 		self:Abort("splitting failed", "Splitting failed."); | 
| Zerotorescue@80 | 349 	end | 
| Zerotorescue@80 | 350 end | 
| Zerotorescue@80 | 351 | 
| Zerotorescue@81 | 352 function mod:Abort(simple, debugMsg) | 
| Zerotorescue@81 | 353 	if debugMsg then | 
| Zerotorescue@81 | 354 		addon:Debug("Aborting:" .. debugMsg); | 
| Zerotorescue@81 | 355 	end | 
| Zerotorescue@81 | 356 	if simple then | 
| Zerotorescue@81 | 357 		print("|cffff0000Aborting: " .. simple .. ".|r"); | 
| Zerotorescue@81 | 358 	end | 
| Zerotorescue@81 | 359 	table.wipe(combinedMoves); | 
| Zerotorescue@81 | 360 	movesSource = nil; | 
| Zerotorescue@80 | 361 | 
| Zerotorescue@81 | 362 	-- Stop timer | 
| Zerotorescue@81 | 363 	self:UnregisterEvent("BAG_UPDATE"); | 
| Zerotorescue@81 | 364 	self:CancelTimer(tmrProcessNext, true); -- silent | 
| Zerotorescue@80 | 365 | 
| Zerotorescue@81 | 366 	self:UnregisterEvent("UI_ERROR_MESSAGE"); | 
| Zerotorescue@80 | 367 end | 
| Zerotorescue@80 | 368 | 
| Zerotorescue@80 | 369 function mod:OnEnable() | 
| Zerotorescue@80 | 370 	Scanner = addon:GetModule("Scanner"); | 
| Zerotorescue@80 | 371 end | 
| Zerotorescue@80 | 372 | 
| Zerotorescue@80 | 373 function mod:OnDisable() | 
| Zerotorescue@80 | 374 	Scanner = nil; | 
| Zerotorescue@81 | 375 | 
| Zerotorescue@81 | 376 	self:Abort(); | 
| Zerotorescue@80 | 377 end |