annotate Modules/Mover.lua @ 109:3bbad0429d87

Now only giving the ?bags are full? message once per item rather then for every queued move. Neater coding for the container functions and prepared mailbox support (although this is not currently planned to be further developed for the moment). Updated todo list to include mailbox support.
author Zerotorescue
date Wed, 12 Jan 2011 22:48:25 +0100
parents 6ae44d372360
children 67bd5057ecb7
rev   line source
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@101 9 function mod:AddMove(itemId, amount, numMissing, numAvailable)
Zerotorescue@80 10 table.insert(queuedMoves, {
Zerotorescue@80 11 id = itemId,
Zerotorescue@80 12 num = amount,
Zerotorescue@101 13 missing = numMissing,
Zerotorescue@101 14 available = numAvailable,
Zerotorescue@80 15 });
Zerotorescue@80 16 end
Zerotorescue@80 17
Zerotorescue@81 18 function mod:HasMoves()
Zerotorescue@81 19 return (#queuedMoves ~= 0);
Zerotorescue@81 20 end
Zerotorescue@81 21
Zerotorescue@101 22 function mod:GetMoves()
Zerotorescue@101 23 return queuedMoves;
Zerotorescue@101 24 end
Zerotorescue@101 25
Zerotorescue@101 26 function mod:ResetQueue()
Zerotorescue@101 27 table.wipe(queuedMoves);
Zerotorescue@101 28 end
Zerotorescue@101 29
Zerotorescue@84 30 if not table.reverse then
Zerotorescue@84 31 table.reverse = function(orig)
Zerotorescue@84 32 local temp = {};
Zerotorescue@84 33 local origLength = #orig;
Zerotorescue@84 34 for i = 1, origLength do
Zerotorescue@84 35 temp[(origLength - i + 1)] = orig[i];
Zerotorescue@84 36 end
Zerotorescue@84 37
Zerotorescue@84 38 -- -- Update the original table (can't do orig = temp as that would change the reference-link instead of the original table)
Zerotorescue@84 39 -- for i, v in pairs(temp) do
Zerotorescue@84 40 -- orig[i] = v;
Zerotorescue@84 41 -- end
Zerotorescue@84 42 return temp; -- for speed we choose to do a return instead
Zerotorescue@84 43 end
Zerotorescue@84 44 end
Zerotorescue@84 45
Zerotorescue@80 46 function mod:BeginMove(location, onFinish)
Zerotorescue@81 47 addon:Debug("BeginMove");
Zerotorescue@80 48
Zerotorescue@80 49 -- Find the outgoing moves
Zerotorescue@80 50 -- 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 51
Zerotorescue@80 52 -- Get a list of items in the source container
Zerotorescue@80 53 local sourceContents = Scanner:CacheLocation(location, false);
Zerotorescue@80 54
Zerotorescue@80 55 local outgoingMoves = {};
Zerotorescue@80 56
Zerotorescue@89 57 addon:Debug("%d moves were queued.", #queuedMoves);
Zerotorescue@82 58
Zerotorescue@81 59 for _, singleMove in pairs(queuedMoves) do
Zerotorescue@80 60 local sourceItem = sourceContents[singleMove.id];
Zerotorescue@80 61 if not sourceItem then
Zerotorescue@101 62 addon:Print(("Can't move %s, this doesn't exist in the source."):format(IdToItemLink(singleMove.id)), addon.Colors.Red);
Zerotorescue@80 63 else
Zerotorescue@82 64 -- We want to move the smallest stacks first to keep stuff pretty (and minimize space usage, splitting a stack takes 2 slots, moving something only 1)
Zerotorescue@80 65 table.sort(sourceItem.locations, function(a, b)
Zerotorescue@81 66 return a.count < b.count;
Zerotorescue@80 67 end);
Zerotorescue@80 68
Zerotorescue@81 69 for _, itemLocation in pairs(sourceItem.locations) do
Zerotorescue@80 70 -- if this location has more items than we need, only move what we need, otherwise move everything in this stack
Zerotorescue@80 71 local movingNum = ((itemLocation.count > singleMove.num and singleMove.num) or itemLocation.count);
Zerotorescue@80 72
Zerotorescue@80 73 table.insert(outgoingMoves, {
Zerotorescue@80 74 itemId = singleMove.id,
Zerotorescue@82 75 num = movingNum,
Zerotorescue@80 76 container = itemLocation.container,
Zerotorescue@80 77 slot = itemLocation.slot,
Zerotorescue@80 78 });
Zerotorescue@80 79
Zerotorescue@80 80 singleMove.num = (singleMove.num - movingNum);
Zerotorescue@80 81
Zerotorescue@80 82 if singleMove.num == 0 then
Zerotorescue@80 83 -- If we have prepared everything we wanted, go to the next queued move
Zerotorescue@81 84 break; -- stop the locations-loop
Zerotorescue@80 85 end
Zerotorescue@80 86 end
Zerotorescue@80 87 end
Zerotorescue@80 88 end
Zerotorescue@82 89
Zerotorescue@89 90 addon:Debug("%d outgoing moves are possible.", #outgoingMoves);
Zerotorescue@80 91
Zerotorescue@80 92 -- No longer needed
Zerotorescue@80 93 table.wipe(queuedMoves);
Zerotorescue@80 94
Zerotorescue@80 95 -- Process every single outgoing move and find fitting targets
Zerotorescue@80 96
Zerotorescue@80 97 -- Get a list of items already in the target container
Zerotorescue@80 98 local targetContents = Scanner:CacheLocation(addon.Locations.Bag, false);
Zerotorescue@80 99
Zerotorescue@80 100 -- Find all empty slots
Zerotorescue@80 101
Zerotorescue@80 102 local emptySlots = {};
Zerotorescue@80 103
Zerotorescue@80 104 local start = 0;
Zerotorescue@80 105 local stop = NUM_BAG_SLOTS;
Zerotorescue@80 106
Zerotorescue@80 107 -- Go through all our bags, including the backpack
Zerotorescue@80 108 for bagId = start, stop do
Zerotorescue@80 109 -- Go through all our slots
Zerotorescue@80 110 for slotId = 1, GetContainerNumSlots(bagId) do
Zerotorescue@82 111 local itemId = GetContainerItemID(bagId, slotId); -- we're scanning our local bags here, so no need to get messy with guild bank support
Zerotorescue@80 112
Zerotorescue@80 113 if not itemId then
Zerotorescue@80 114 table.insert(emptySlots, {
Zerotorescue@81 115 container = bagId,
Zerotorescue@81 116 slot = slotId,
Zerotorescue@80 117 });
Zerotorescue@80 118 end
Zerotorescue@80 119 end
Zerotorescue@80 120 end
Zerotorescue@82 121
Zerotorescue@89 122 addon:Debug("%d empty slots are available.", #emptySlots);
Zerotorescue@80 123
Zerotorescue@81 124 -- Remember where we're moving from
Zerotorescue@81 125 movesSource = location;
Zerotorescue@81 126
Zerotorescue@84 127 local backup = 0;
Zerotorescue@84 128
Zerotorescue@80 129 while #outgoingMoves ~= 0 do
Zerotorescue@80 130 -- A not equal-comparison should be quicker than a larger/smaller than-comparison
Zerotorescue@80 131
Zerotorescue@81 132 for _, outgoingMove in pairs(outgoingMoves) do
Zerotorescue@80 133 -- itemId will be set to nil when this outgoing move was processed - sanity check
Zerotorescue@80 134 if outgoingMove.itemId then
Zerotorescue@80 135 local targetItem = targetContents[outgoingMove.itemId];
Zerotorescue@80 136
Zerotorescue@80 137 if not targetItem then
Zerotorescue@80 138 -- grab an empty slot
Zerotorescue@80 139 -- make new instance of ItemMove
Zerotorescue@80 140 -- 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 141
Zerotorescue@80 142 local firstAvailableSlot = emptySlots[1];
Zerotorescue@80 143
Zerotorescue@80 144 if not firstAvailableSlot then
Zerotorescue@98 145 addon:Print(("Bags are full. Skipping %s."):format(IdToItemLink(outgoingMove.itemId)), addon.Colors.Orange);
Zerotorescue@80 146
Zerotorescue@82 147 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@109 148
Zerotorescue@109 149 -- Not a single item with this item id can be moved, since we only want the bags are full announcement once, we remove all other moves with this item id
Zerotorescue@109 150 for _, otherMove in pairs(outgoingMoves) do
Zerotorescue@109 151 if otherMove.itemId and otherMove.itemId == outgoingMove.itemId then
Zerotorescue@109 152 otherMove.itemId = nil;
Zerotorescue@109 153 end
Zerotorescue@109 154 end
Zerotorescue@80 155 else
Zerotorescue@80 156 table.insert(combinedMoves, {
Zerotorescue@82 157 itemId = outgoingMove.itemId,
Zerotorescue@82 158 num = outgoingMove.num,
Zerotorescue@80 159 sourceContainer = outgoingMove.container,
Zerotorescue@80 160 sourceSlot = outgoingMove.slot,
Zerotorescue@80 161 targetContainer = firstAvailableSlot.container,
Zerotorescue@80 162 targetSlot = firstAvailableSlot.slot,
Zerotorescue@80 163 });
Zerotorescue@80 164
Zerotorescue@80 165 -- We filled an empty slot so the target contents now has one more item,
Zerotorescue@80 166 -- make a new instance of the ItemMove class so any additional items with this id can be stacked on top of it
Zerotorescue@81 167 local itemMove = addon.ContainerItem:New();
Zerotorescue@82 168 itemMove:AddLocation(firstAvailableSlot.container, firstAvailableSlot.slot, outgoingMove.num);
Zerotorescue@80 169 targetContents[outgoingMove.itemId] = itemMove;
Zerotorescue@80 170
Zerotorescue@81 171 table.remove(emptySlots, 1); -- no longer empty
Zerotorescue@80 172
Zerotorescue@82 173 outgoingMove.num = 0; -- nothing remaining - sanity check
Zerotorescue@80 174 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@80 175 end
Zerotorescue@80 176 else
Zerotorescue@80 177 -- Find the maximum stack size for this item
Zerotorescue@80 178 local itemStackCount = select(8, GetItemInfo(outgoingMove.itemId));
Zerotorescue@80 179
Zerotorescue@80 180 -- We want to move to the largest stacks first to keep stuff pretty
Zerotorescue@80 181 table.sort(targetItem.locations, function(a, b)
Zerotorescue@81 182 return a.count > b.count;
Zerotorescue@80 183 end);
Zerotorescue@80 184
Zerotorescue@81 185 for _, itemLocation in pairs(targetItem.locations) do
Zerotorescue@82 186 if itemLocation.count < itemStackCount and outgoingMove.num > 0 then
Zerotorescue@80 187 -- Check if this stack isn't already full (and we still need to move this item)
Zerotorescue@80 188
Zerotorescue@80 189 local remainingSpace = (itemStackCount - itemLocation.count);
Zerotorescue@84 190 if remainingSpace >= outgoingMove.num then
Zerotorescue@80 191 -- Enough room to move this entire stack
Zerotorescue@80 192 -- Deposit this item and then forget this outgoing move as everything in it was processed
Zerotorescue@80 193
Zerotorescue@80 194 table.insert(combinedMoves, {
Zerotorescue@82 195 itemId = outgoingMove.itemId,
Zerotorescue@82 196 num = outgoingMove.num,
Zerotorescue@80 197 sourceContainer = outgoingMove.container,
Zerotorescue@80 198 sourceSlot = outgoingMove.slot,
Zerotorescue@80 199 targetContainer = itemLocation.container,
Zerotorescue@80 200 targetSlot = itemLocation.slot,
Zerotorescue@80 201 });
Zerotorescue@80 202
Zerotorescue@82 203 itemLocation.count = (itemLocation.count + outgoingMove.num);
Zerotorescue@84 204 outgoingMove.num = 0; -- nothing remaining
Zerotorescue@80 205 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table
Zerotorescue@80 206 break; -- stop the locations-loop
Zerotorescue@80 207 else
Zerotorescue@80 208 -- Deposit this item but don't remove the outgoing move as there are some items left to move
Zerotorescue@80 209
Zerotorescue@80 210 table.insert(combinedMoves, {
Zerotorescue@82 211 itemId = outgoingMove.itemId,
Zerotorescue@82 212 num = outgoingMove.num,
Zerotorescue@80 213 sourceContainer = outgoingMove.container,
Zerotorescue@80 214 sourceSlot = outgoingMove.slot,
Zerotorescue@80 215 targetContainer = itemLocation.container,
Zerotorescue@80 216 targetSlot = itemLocation.slot,
Zerotorescue@80 217 });
Zerotorescue@80 218
Zerotorescue@80 219 -- The target will be full when we complete, but the source will still have remaining items left to be moved
Zerotorescue@80 220 itemLocation.count = itemStackCount;
Zerotorescue@82 221 outgoingMove.num = (outgoingMove.num - remainingSpace);
Zerotorescue@80 222 end
Zerotorescue@80 223 end
Zerotorescue@80 224 end
Zerotorescue@80 225
Zerotorescue@82 226 if outgoingMove.num > 0 then
Zerotorescue@80 227 -- We went through all matching items and checked their stack sizes if we could move this there, no room available
Zerotorescue@80 228 -- 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@84 229 targetContents[outgoingMove.itemId] = nil;
Zerotorescue@80 230 end
Zerotorescue@80 231 end
Zerotorescue@80 232 end
Zerotorescue@80 233 end
Zerotorescue@80 234
Zerotorescue@80 235 -- Loop through the array to find items that should be removed, start with the last element or the loop would break
Zerotorescue@80 236 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 237 while numOutgoingMoves ~= 0 do
Zerotorescue@80 238 -- A not equal-comparison should be quicker than a larger/smaller than-comparison
Zerotorescue@80 239
Zerotorescue@80 240 -- Check if the item id is nil, this is set to nil when this outgoing move has been processed
Zerotorescue@84 241 if not outgoingMoves[numOutgoingMoves].itemId or outgoingMoves[numOutgoingMoves].num == 0 then
Zerotorescue@80 242 -- Remove this element from the array
Zerotorescue@80 243 table.remove(outgoingMoves, numOutgoingMoves);
Zerotorescue@80 244 end
Zerotorescue@80 245
Zerotorescue@80 246 -- Proceed with the next element (or previous considering we're going from last to first)
Zerotorescue@80 247 numOutgoingMoves = (numOutgoingMoves - 1);
Zerotorescue@80 248 end
Zerotorescue@84 249
Zerotorescue@89 250 addon:Debug("%d moves remaining.", #outgoingMoves);
Zerotorescue@84 251
Zerotorescue@84 252 backup = (backup + 1);
Zerotorescue@84 253 if backup > 1000 then
Zerotorescue@84 254 dump(nil, outgoingMoves);
Zerotorescue@84 255 table.wipe(outgoingMoves);
Zerotorescue@84 256 self:Abort("mover crashed", "Error preparing moves, hit an endless loop");
Zerotorescue@84 257 onFinish();
Zerotorescue@84 258 return;
Zerotorescue@84 259 end
Zerotorescue@80 260 end
Zerotorescue@84 261
Zerotorescue@84 262 -- 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@84 263 combinedMoves = table.reverse(combinedMoves);
Zerotorescue@82 264
Zerotorescue@89 265 addon:Debug("%d moves should be possible.", #combinedMoves);
Zerotorescue@80 266
Zerotorescue@80 267 -- No longer needed
Zerotorescue@80 268 table.wipe(emptySlots);
Zerotorescue@80 269
Zerotorescue@81 270 self:ProcessMove();
Zerotorescue@80 271
Zerotorescue@82 272 -- Even though we aren't completely done yet, allow requeueing
Zerotorescue@81 273 onFinish();
Zerotorescue@80 274 end
Zerotorescue@80 275
Zerotorescue@109 276 local ContainerFunctions = {
Zerotorescue@109 277 [addon.Locations.Bag] = {
Zerotorescue@109 278 GetItemId = GetContainerItemID,
Zerotorescue@109 279 PickupItem = SplitContainerItem,
Zerotorescue@109 280 IsLocked = function(sourceContainer, sourceSlot)
Zerotorescue@109 281 return select(3, GetContainerItemInfo(sourceContainer, sourceSlot);
Zerotorescue@109 282 end,
Zerotorescue@109 283 },
Zerotorescue@109 284 [addon.Locations.Bank] = {
Zerotorescue@109 285 GetItemId = GetContainerItemID,
Zerotorescue@109 286 PickupItem = SplitContainerItem,
Zerotorescue@109 287 IsLocked = function(sourceContainer, sourceSlot)
Zerotorescue@109 288 return select(3, GetContainerItemInfo(sourceContainer, sourceSlot);
Zerotorescue@109 289 end,
Zerotorescue@109 290 },
Zerotorescue@109 291 [addon.Locations.Guild] = {
Zerotorescue@109 292 GetItemId = function(tabId, slotId)
Zerotorescue@109 293 return addon:GetItemId(GetGuildBankItemLink(tabId, slotId));
Zerotorescue@109 294 end,
Zerotorescue@109 295 PickupItem = SplitGuildBankItem,
Zerotorescue@109 296 IsLocked = function(sourceContainer, sourceSlot)
Zerotorescue@109 297 return select(3, GetGuildBankItemInfo(sourceContainer, sourceSlot);
Zerotorescue@109 298 end,
Zerotorescue@109 299 },
Zerotorescue@109 300 --[[ Even though support is possible, it will require a little more work than just this and there are currently higher priorities
Zerotorescue@109 301 [addon.Locations.Mailbox] = {
Zerotorescue@109 302 GetItemId = function(mailIndex, attachmentId)
Zerotorescue@109 303 return addon:GetItemId(GetInboxItemLink(mailIndex, attachmentId));
Zerotorescue@109 304 end,
Zerotorescue@109 305 PickupItem = TakeInboxItem,
Zerotorescue@109 306 IsLocked = function() return false; end,
Zerotorescue@109 307 DoNotDrop = true,
Zerotorescue@109 308 },]]
Zerotorescue@109 309 };
Zerotorescue@109 310
Zerotorescue@81 311 function mod:ProcessMove()
Zerotorescue@81 312 addon:Debug("ProcessMove");
Zerotorescue@81 313
Zerotorescue@81 314 if #combinedMoves == 0 then
Zerotorescue@98 315 addon:Print("Nothing to move.");
Zerotorescue@81 316
Zerotorescue@81 317 self:Abort();
Zerotorescue@81 318
Zerotorescue@81 319 return;
Zerotorescue@81 320 end
Zerotorescue@81 321
Zerotorescue@98 322 -- Make sure nothing is at the mouse
Zerotorescue@98 323 ClearCursor();
Zerotorescue@98 324
Zerotorescue@88 325 self:RegisterEvent("ITEM_LOCK_CHANGED");
Zerotorescue@81 326 self:RegisterEvent("UI_ERROR_MESSAGE");
Zerotorescue@81 327
Zerotorescue@80 328 -- combinedMoves now has all moves in it (source -> target)
Zerotorescue@80 329 -- go through list, move everything inside it
Zerotorescue@81 330 -- add source and target to lists, if either is already in this list, skip the move
Zerotorescue@81 331 -- repeat every few seconds until we're completely done
Zerotorescue@80 332
Zerotorescue@80 333 local sourceLocationsLocked = {};
Zerotorescue@80 334 local targetLocationsLocked = {};
Zerotorescue@80 335
Zerotorescue@82 336 local combinedMovesOriginalLength = #combinedMoves;
Zerotorescue@82 337 local numCurrentMove = combinedMovesOriginalLength;
Zerotorescue@80 338 while numCurrentMove ~= 0 do
Zerotorescue@80 339 local move = combinedMoves[numCurrentMove];
Zerotorescue@80 340
Zerotorescue@109 341 local isSourceLocked = ((sourceLocationsLocked[move.sourceContainer] and sourceLocationsLocked[move.sourceContainer][move.sourceSlot]) or ContainerFunctions[movesSource].IsLocked(move.sourceContainer, move.sourceSlot));
Zerotorescue@109 342 -- Target are always the local bags
Zerotorescue@109 343 local isTargetLocked = ((targetLocationsLocked[move.targetContainer] and targetLocationsLocked[move.targetContainer][move.targetSlot]) or ContainerFunctions[addon.Locations.Bag].IsLocked(move.targetContainer, move.targetSlot));
Zerotorescue@88 344
Zerotorescue@89 345 if move and not isSourceLocked and not isTargetLocked then
Zerotorescue@98 346 addon:Print(("Moving %dx%s."):format(move.num, IdToItemLink(move.itemId)));
Zerotorescue@80 347
Zerotorescue@89 348 addon:Debug("Moving %dx%s from (%d,%d) to (%d,%d)", move.num, IdToItemLink(move.itemId), move.sourceContainer, move.sourceSlot, move.targetContainer, move.targetSlot);
Zerotorescue@81 349
Zerotorescue@109 350 if ContainerFunctions[movesSource].GetItemId(move.sourceContainer, move.sourceSlot) ~= move.itemId then
Zerotorescue@81 351 self:Abort("source changed", "Source (" .. move.sourceContainer .. "," .. move.sourceSlot .. ") is not " .. IdToItemLink(move.itemId));
Zerotorescue@81 352 return;
Zerotorescue@81 353 end
Zerotorescue@81 354
Zerotorescue@80 355 -- Pickup stack
Zerotorescue@109 356 ContainerFunctions[movesSource].PickupItem(move.sourceContainer, move.sourceSlot, move.num);
Zerotorescue@80 357
Zerotorescue@80 358 -- Remember we picked this item up and thus it is now locked
Zerotorescue@80 359 if not sourceLocationsLocked[move.sourceContainer] then
Zerotorescue@80 360 sourceLocationsLocked[move.sourceContainer] = {};
Zerotorescue@80 361 end
Zerotorescue@80 362 sourceLocationsLocked[move.sourceContainer][move.sourceSlot] = true;
Zerotorescue@80 363
Zerotorescue@109 364 if movesSource ~= addon.Locations.Bank or CursorHasItem() then -- CursorHasItem only works when moving outside of the bank
Zerotorescue@84 365 -- We are moving into our local bags, so the below must check normal
Zerotorescue@109 366 local targetItemId = ContainerFunctions[movesSource].get(move.targetContainer, move.targetSlot);
Zerotorescue@84 367 if targetItemId and targetItemId ~= move.itemId then
Zerotorescue@81 368 self:Abort("target changed", "Target (" .. move.targetContainer .. "," .. move.targetSlot .. ") is not " .. IdToItemLink(move.itemId) .. " nor empty");
Zerotorescue@81 369 return;
Zerotorescue@81 370 end
Zerotorescue@81 371
Zerotorescue@82 372 -- And drop it (this is always a local bag so no need to do any guild-checks)
Zerotorescue@80 373 PickupContainerItem(move.targetContainer, move.targetSlot);
Zerotorescue@80 374
Zerotorescue@80 375 -- Remember we dropped an item here and thus this is now locked
Zerotorescue@81 376 if not targetLocationsLocked[move.targetContainer] then
Zerotorescue@81 377 targetLocationsLocked[move.targetContainer] = {};
Zerotorescue@80 378 end
Zerotorescue@81 379 targetLocationsLocked[move.targetContainer][move.targetSlot] = true;
Zerotorescue@80 380
Zerotorescue@80 381 -- This move was processed
Zerotorescue@80 382 table.remove(combinedMoves, numCurrentMove);
Zerotorescue@81 383 else
Zerotorescue@81 384 self:Abort("item disappeared from mouse", "Couldn't move " .. IdToItemLink(move.itemId) .. ", CursorHasItem() is false");
Zerotorescue@81 385 return;
Zerotorescue@80 386 end
Zerotorescue@80 387 end
Zerotorescue@80 388
Zerotorescue@80 389 -- Proceed with the next element (or previous considering we're going from last to first)
Zerotorescue@80 390 numCurrentMove = (numCurrentMove - 1);
Zerotorescue@80 391 end
Zerotorescue@81 392
Zerotorescue@89 393 addon:Debug("%d moves processed. %d moves remaining.", (combinedMovesOriginalLength - #combinedMoves), #combinedMoves);
Zerotorescue@82 394
Zerotorescue@81 395 if #combinedMoves == 0 then
Zerotorescue@98 396 addon:Print("Finished.", addon.Colors.Green);
Zerotorescue@81 397
Zerotorescue@81 398 self:Abort();
Zerotorescue@81 399
Zerotorescue@81 400 return;
Zerotorescue@81 401 end
Zerotorescue@80 402 end
Zerotorescue@80 403
Zerotorescue@80 404 local tmrProcessNext;
Zerotorescue@88 405 function mod:ITEM_LOCK_CHANGED()
Zerotorescue@81 406 self:CancelTimer(tmrProcessNext, true); -- silent
Zerotorescue@89 407 tmrProcessNext = self:ScheduleTimer("ProcessMove", .5);
Zerotorescue@80 408 end
Zerotorescue@80 409
Zerotorescue@81 410 function IdToItemLink(itemId)
Zerotorescue@81 411 local itemLink = select(2, GetItemInfo(itemId));
Zerotorescue@81 412 itemLink = itemLink or "Unknown (" .. itemId .. ")";
Zerotorescue@81 413 return itemLink;
Zerotorescue@81 414 end
Zerotorescue@81 415
Zerotorescue@81 416 function mod:UI_ERROR_MESSAGE(e, errorMessage)
Zerotorescue@81 417 if errorMessage == ERR_SPLIT_FAILED then
Zerotorescue@81 418 self:Abort("splitting failed", "Splitting failed.");
Zerotorescue@80 419 end
Zerotorescue@80 420 end
Zerotorescue@80 421
Zerotorescue@81 422 function mod:Abort(simple, debugMsg)
Zerotorescue@81 423 if debugMsg then
Zerotorescue@89 424 addon:Debug("Aborting:%s", debugMsg);
Zerotorescue@81 425 end
Zerotorescue@81 426 if simple then
Zerotorescue@98 427 addon:Print(("Aborting: %s."):format(simple), addon.Colors.Red);
Zerotorescue@81 428 end
Zerotorescue@81 429 table.wipe(combinedMoves);
Zerotorescue@81 430 movesSource = nil;
Zerotorescue@80 431
Zerotorescue@98 432 -- Make sure nothing is at the mouse
Zerotorescue@98 433 ClearCursor();
Zerotorescue@98 434
Zerotorescue@81 435 -- Stop timer
Zerotorescue@89 436 self:UnregisterEvent("ITEM_LOCK_CHANGED");
Zerotorescue@81 437 self:CancelTimer(tmrProcessNext, true); -- silent
Zerotorescue@80 438
Zerotorescue@81 439 self:UnregisterEvent("UI_ERROR_MESSAGE");
Zerotorescue@80 440 end
Zerotorescue@80 441
Zerotorescue@80 442 function mod:OnEnable()
Zerotorescue@80 443 Scanner = addon:GetModule("Scanner");
Zerotorescue@80 444 end
Zerotorescue@80 445
Zerotorescue@80 446 function mod:OnDisable()
Zerotorescue@80 447 Scanner = nil;
Zerotorescue@81 448
Zerotorescue@81 449 self:Abort();
Zerotorescue@80 450 end