Mercurial > wow > inventory
comparison Modules/Mover.lua @ 122:6724bc8eface
Reduced usage of global functions by defining them locally.
| author | Zerotorescue |
|---|---|
| date | Sat, 15 Jan 2011 18:52:01 +0100 |
| parents | 00cf4fc1697f |
| children | 84e38318f569 |
comparison
equal
deleted
inserted
replaced
| 121:ca6280dc2f5b | 122:6724bc8eface |
|---|---|
| 1 local addon = select(2, ...); | 1 local addon = select(2, ...); |
| 2 local mod = addon:NewModule("Mover", "AceEvent-3.0", "AceTimer-3.0"); | 2 local mod = addon:NewModule("Mover", "AceEvent-3.0", "AceTimer-3.0"); |
| 3 | |
| 4 local _G = _G; | |
| 5 local select, pairs = _G.select, _G.pairs; | |
| 6 local tinsert, twipe, treverse, tsort, tremove = _G.table.insert, _G.table.wipe, _G.table.reverse, _G.table.sort, _G.table.remove; | |
| 3 | 7 |
| 4 local Scanner; | 8 local Scanner; |
| 5 local queuedMoves = {}; -- table storing all queued moves before BeginMove is called | 9 local queuedMoves = {}; -- table storing all queued moves before BeginMove is called |
| 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 #) | 10 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 #) |
| 7 local movesSource; | 11 local movesSource; |
| 56 Event = "BAG_UPDATE", | 60 Event = "BAG_UPDATE", |
| 57 }, | 61 }, |
| 58 }; | 62 }; |
| 59 | 63 |
| 60 function mod:AddMove(itemId, amount, numMissing, numAvailable, cost) | 64 function mod:AddMove(itemId, amount, numMissing, numAvailable, cost) |
| 61 table.insert(queuedMoves, { | 65 tinsert(queuedMoves, { |
| 62 ["itemId"] = itemId, | 66 ["itemId"] = itemId, |
| 63 ["num"] = amount, -- can not be unlimited | 67 ["num"] = amount, -- can not be unlimited |
| 64 ["missing"] = numMissing, | 68 ["missing"] = numMissing, |
| 65 ["available"] = numAvailable, | 69 ["available"] = numAvailable, |
| 66 ["cost"] = cost, | 70 ["cost"] = cost, |
| 74 function mod:GetMoves() | 78 function mod:GetMoves() |
| 75 return queuedMoves; | 79 return queuedMoves; |
| 76 end | 80 end |
| 77 | 81 |
| 78 function mod:ResetQueue() | 82 function mod:ResetQueue() |
| 79 table.wipe(queuedMoves); | 83 twipe(queuedMoves); |
| 80 end | 84 end |
| 81 | 85 |
| 82 if not table.reverse then | 86 if not treverse then |
| 83 table.reverse = function(orig) | 87 treverse = function(orig) |
| 84 local temp = {}; | 88 local temp = {}; |
| 85 local origLength = #orig; | 89 local origLength = #orig; |
| 86 for i = 1, origLength do | 90 for i = 1, origLength do |
| 87 temp[(origLength - i + 1)] = orig[i]; | 91 temp[(origLength - i + 1)] = orig[i]; |
| 88 end | 92 end |
| 104 for slotId = 1, GetContainerNumSlots(bagId) do | 108 for slotId = 1, GetContainerNumSlots(bagId) do |
| 105 local itemId = GetContainerItemID(bagId, slotId); -- we're scanning our local bags here, so no need to get messy with guild bank support | 109 local itemId = GetContainerItemID(bagId, slotId); -- we're scanning our local bags here, so no need to get messy with guild bank support |
| 106 local bagFamily = select(2, GetContainerNumFreeSlots(bagId)); | 110 local bagFamily = select(2, GetContainerNumFreeSlots(bagId)); |
| 107 | 111 |
| 108 if not itemId then | 112 if not itemId then |
| 109 table.insert(emptySlots, { | 113 tinsert(emptySlots, { |
| 110 ["container"] = bagId, | 114 ["container"] = bagId, |
| 111 ["slot"] = slotId, | 115 ["slot"] = slotId, |
| 112 ["family"] = bagFamily, | 116 ["family"] = bagFamily, |
| 113 }); | 117 }); |
| 114 end | 118 end |
| 152 local sourceItem = sourceContents[singleMove.itemId]; | 156 local sourceItem = sourceContents[singleMove.itemId]; |
| 153 if not sourceItem then | 157 if not sourceItem then |
| 154 addon:Print(("Can't move %s, this doesn't exist in the source."):format(IdToItemLink(singleMove.itemId)), addon.Colors.Red); | 158 addon:Print(("Can't move %s, this doesn't exist in the source."):format(IdToItemLink(singleMove.itemId)), addon.Colors.Red); |
| 155 else | 159 else |
| 156 -- 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) | 160 -- 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) |
| 157 table.sort(sourceItem.locations, function(a, b) | 161 tsort(sourceItem.locations, function(a, b) |
| 158 -- -1 indicates unlimited, this is always more than an actual amount | 162 -- -1 indicates unlimited, this is always more than an actual amount |
| 159 if a.count == -1 then | 163 if a.count == -1 then |
| 160 return false; | 164 return false; |
| 161 elseif b.count == -1 then | 165 elseif b.count == -1 then |
| 162 return true; | 166 return true; |
| 177 | 181 |
| 178 if stackSize then | 182 if stackSize then |
| 179 while movingNum > stackSize do | 183 while movingNum > stackSize do |
| 180 -- Move a single stack size while the amount remaining to be moved is above the stack size num | 184 -- Move a single stack size while the amount remaining to be moved is above the stack size num |
| 181 | 185 |
| 182 table.insert(outgoingMoves, { | 186 tinsert(outgoingMoves, { |
| 183 ["itemId"] = singleMove.itemId, | 187 ["itemId"] = singleMove.itemId, |
| 184 ["num"] = stackSize, | 188 ["num"] = stackSize, |
| 185 ["container"] = itemLocation.container, | 189 ["container"] = itemLocation.container, |
| 186 ["slot"] = itemLocation.slot, | 190 ["slot"] = itemLocation.slot, |
| 187 }); | 191 }); |
| 190 singleMove.num = (singleMove.num - stackSize); | 194 singleMove.num = (singleMove.num - stackSize); |
| 191 end | 195 end |
| 192 end | 196 end |
| 193 end | 197 end |
| 194 | 198 |
| 195 table.insert(outgoingMoves, { | 199 tinsert(outgoingMoves, { |
| 196 ["itemId"] = singleMove.itemId, | 200 ["itemId"] = singleMove.itemId, |
| 197 ["num"] = movingNum, | 201 ["num"] = movingNum, |
| 198 ["container"] = itemLocation.container, | 202 ["container"] = itemLocation.container, |
| 199 ["slot"] = itemLocation.slot, | 203 ["slot"] = itemLocation.slot, |
| 200 }); | 204 }); |
| 210 end | 214 end |
| 211 | 215 |
| 212 addon:Debug("%d outgoing moves are possible.", #outgoingMoves); | 216 addon:Debug("%d outgoing moves are possible.", #outgoingMoves); |
| 213 | 217 |
| 214 -- No longer needed | 218 -- No longer needed |
| 215 table.wipe(queuedMoves); | 219 twipe(queuedMoves); |
| 216 | 220 |
| 217 | 221 |
| 218 | 222 |
| 219 -- Process every single outgoing move and find fitting targets | 223 -- Process every single outgoing move and find fitting targets |
| 220 | 224 |
| 262 end | 266 end |
| 263 end | 267 end |
| 264 else | 268 else |
| 265 -- Consume empty slot | 269 -- Consume empty slot |
| 266 | 270 |
| 267 table.insert(combinedMoves, { | 271 tinsert(combinedMoves, { |
| 268 ["itemId"] = outgoingMove.itemId, | 272 ["itemId"] = outgoingMove.itemId, |
| 269 ["num"] = outgoingMove.num, | 273 ["num"] = outgoingMove.num, |
| 270 ["sourceContainer"] = outgoingMove.container, | 274 ["sourceContainer"] = outgoingMove.container, |
| 271 ["sourceSlot"] = outgoingMove.slot, | 275 ["sourceSlot"] = outgoingMove.slot, |
| 272 ["targetContainer"] = firstAvailableSlot.container, | 276 ["targetContainer"] = firstAvailableSlot.container, |
| 277 -- make a new instance of the ItemMove class so any additional items with this id can be stacked on top of it | 281 -- make a new instance of the ItemMove class so any additional items with this id can be stacked on top of it |
| 278 local itemMove = addon.ContainerItem:New(); | 282 local itemMove = addon.ContainerItem:New(); |
| 279 itemMove:AddLocation(firstAvailableSlot.container, firstAvailableSlot.slot, outgoingMove.num); | 283 itemMove:AddLocation(firstAvailableSlot.container, firstAvailableSlot.slot, outgoingMove.num); |
| 280 targetContents[outgoingMove.itemId] = itemMove; | 284 targetContents[outgoingMove.itemId] = itemMove; |
| 281 | 285 |
| 282 table.remove(emptySlots, 1); -- no longer empty | 286 tremove(emptySlots, 1); -- no longer empty |
| 283 | 287 |
| 284 outgoingMove.num = 0; -- nothing remaining - sanity check | 288 outgoingMove.num = 0; -- nothing remaining - sanity check |
| 285 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table | 289 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table |
| 286 end | 290 end |
| 287 else | 291 else |
| 288 -- Find the maximum stack size for this item | 292 -- Find the maximum stack size for this item |
| 289 local itemStackCount = select(8, GetItemInfo(outgoingMove.itemId)); | 293 local itemStackCount = select(8, GetItemInfo(outgoingMove.itemId)); |
| 290 | 294 |
| 291 -- We want to move to the largest stacks first to keep stuff pretty | 295 -- We want to move to the largest stacks first to keep stuff pretty |
| 292 table.sort(targetItem.locations, function(a, b) | 296 tsort(targetItem.locations, function(a, b) |
| 293 return a.count > b.count; | 297 return a.count > b.count; |
| 294 end); | 298 end); |
| 295 | 299 |
| 296 for _, itemLocation in pairs(targetItem.locations) do | 300 for _, itemLocation in pairs(targetItem.locations) do |
| 297 if itemLocation.count < itemStackCount and outgoingMove.num > 0 then | 301 if itemLocation.count < itemStackCount and outgoingMove.num > 0 then |
| 300 local remainingSpace = (itemStackCount - itemLocation.count); | 304 local remainingSpace = (itemStackCount - itemLocation.count); |
| 301 if remainingSpace >= outgoingMove.num then | 305 if remainingSpace >= outgoingMove.num then |
| 302 -- Enough room to move this entire stack | 306 -- Enough room to move this entire stack |
| 303 -- Deposit this item and then forget this outgoing move as everything in it was processed | 307 -- Deposit this item and then forget this outgoing move as everything in it was processed |
| 304 | 308 |
| 305 table.insert(combinedMoves, { | 309 tinsert(combinedMoves, { |
| 306 ["itemId"] = outgoingMove.itemId, | 310 ["itemId"] = outgoingMove.itemId, |
| 307 ["num"] = outgoingMove.num, | 311 ["num"] = outgoingMove.num, |
| 308 ["sourceContainer"] = outgoingMove.container, | 312 ["sourceContainer"] = outgoingMove.container, |
| 309 ["sourceSlot"] = outgoingMove.slot, | 313 ["sourceSlot"] = outgoingMove.slot, |
| 310 ["targetContainer"] = itemLocation.container, | 314 ["targetContainer"] = itemLocation.container, |
| 316 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table | 320 outgoingMove.itemId = nil; -- remove this record from the outgoingMoves-table |
| 317 break; -- stop the locations-loop | 321 break; -- stop the locations-loop |
| 318 else | 322 else |
| 319 -- Deposit this item but don't remove the outgoing move as there are some items left to move | 323 -- Deposit this item but don't remove the outgoing move as there are some items left to move |
| 320 | 324 |
| 321 table.insert(combinedMoves, { | 325 tinsert(combinedMoves, { |
| 322 ["itemId"] = outgoingMove.itemId, | 326 ["itemId"] = outgoingMove.itemId, |
| 323 ["num"] = outgoingMove.num, | 327 ["num"] = outgoingMove.num, |
| 324 ["sourceContainer"] = outgoingMove.container, | 328 ["sourceContainer"] = outgoingMove.container, |
| 325 ["sourceSlot"] = outgoingMove.slot, | 329 ["sourceSlot"] = outgoingMove.slot, |
| 326 ["targetContainer"] = itemLocation.container, | 330 ["targetContainer"] = itemLocation.container, |
| 349 -- A not equal-comparison should be quicker than a larger/smaller than-comparison | 353 -- A not equal-comparison should be quicker than a larger/smaller than-comparison |
| 350 | 354 |
| 351 -- Check if the item id is nil, this is set to nil when this outgoing move has been processed | 355 -- Check if the item id is nil, this is set to nil when this outgoing move has been processed |
| 352 if not outgoingMoves[numOutgoingMoves].itemId or outgoingMoves[numOutgoingMoves].num == 0 then | 356 if not outgoingMoves[numOutgoingMoves].itemId or outgoingMoves[numOutgoingMoves].num == 0 then |
| 353 -- Remove this element from the array | 357 -- Remove this element from the array |
| 354 table.remove(outgoingMoves, numOutgoingMoves); | 358 tremove(outgoingMoves, numOutgoingMoves); |
| 355 end | 359 end |
| 356 | 360 |
| 357 -- Proceed with the next element (or previous considering we're going from last to first) | 361 -- Proceed with the next element (or previous considering we're going from last to first) |
| 358 numOutgoingMoves = (numOutgoingMoves - 1); | 362 numOutgoingMoves = (numOutgoingMoves - 1); |
| 359 end | 363 end |
| 360 | 364 |
| 361 addon:Debug("%d moves remaining.", #outgoingMoves); | 365 addon:Debug("%d moves remaining.", #outgoingMoves); |
| 362 | 366 |
| 363 backup = (backup + 1); | 367 backup = (backup + 1); |
| 364 if backup > 1000 then | 368 if backup > 1000 then |
| 365 table.wipe(outgoingMoves); | 369 twipe(outgoingMoves); |
| 366 self:Abort("mover crashed", "Error preparing moves, hit an endless loop"); | 370 self:Abort("mover crashed", "Error preparing moves, hit an endless loop"); |
| 367 onFinish(); | 371 onFinish(); |
| 368 return; | 372 return; |
| 369 end | 373 end |
| 370 end | 374 end |
| 371 | 375 |
| 372 -- 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 | 376 -- 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 |
| 373 combinedMoves = table.reverse(combinedMoves); | 377 combinedMoves = treverse(combinedMoves); |
| 374 | 378 |
| 375 addon:Debug("%d moves should be possible.", #combinedMoves); | 379 addon:Debug("%d moves should be possible.", #combinedMoves); |
| 376 | 380 |
| 377 -- No longer needed | 381 -- No longer needed |
| 378 table.wipe(emptySlots); | 382 twipe(emptySlots); |
| 379 | 383 |
| 380 self:ProcessMove(); | 384 self:ProcessMove(); |
| 381 | 385 |
| 382 -- Even though we aren't completely done yet, allow requeueing | 386 -- Even though we aren't completely done yet, allow requeueing |
| 383 onFinish(); | 387 onFinish(); |
| 407 | 411 |
| 408 if movesSource == addon.Locations.Mailbox then | 412 if movesSource == addon.Locations.Mailbox then |
| 409 MailAddonBusy = addon:GetName(); | 413 MailAddonBusy = addon:GetName(); |
| 410 | 414 |
| 411 -- Since mailbox indexes change as mail is emptied (emptied mail is automatically deleted, thus number 50 would become 49 when 1 disappears), we must start with the last mail first | 415 -- Since mailbox indexes change as mail is emptied (emptied mail is automatically deleted, thus number 50 would become 49 when 1 disappears), we must start with the last mail first |
| 412 table.sort(combinedMoves, function(a, b) | 416 tsort(combinedMoves, function(a, b) |
| 413 return a.sourceContainer < b.sourceContainer; | 417 return a.sourceContainer < b.sourceContainer; |
| 414 end); | 418 end); |
| 415 end | 419 end |
| 416 | 420 |
| 417 self:RegisterEvent(ContainerFunctions[movesSource].Event, "SourceUpdated"); | 421 self:RegisterEvent(ContainerFunctions[movesSource].Event, "SourceUpdated"); |
| 480 targetLocationsLocked[move.targetContainer] = {}; | 484 targetLocationsLocked[move.targetContainer] = {}; |
| 481 end | 485 end |
| 482 targetLocationsLocked[move.targetContainer][move.targetSlot] = true; | 486 targetLocationsLocked[move.targetContainer][move.targetSlot] = true; |
| 483 | 487 |
| 484 -- This move was processed | 488 -- This move was processed |
| 485 table.remove(combinedMoves, numCurrentMove); | 489 tremove(combinedMoves, numCurrentMove); |
| 486 else | 490 else |
| 487 self:Abort("item disappeared from mouse", "Couldn't move " .. IdToItemLink(move.itemId) .. ", CursorHasItem() is false"); | 491 self:Abort("item disappeared from mouse", "Couldn't move " .. IdToItemLink(move.itemId) .. ", CursorHasItem() is false"); |
| 488 return; | 492 return; |
| 489 end | 493 end |
| 490 else | 494 else |
| 491 -- When items are deposit automatically we still need to remember when a move has been processed | 495 -- When items are deposit automatically we still need to remember when a move has been processed |
| 492 | 496 |
| 493 -- This move was processed | 497 -- This move was processed |
| 494 table.remove(combinedMoves, numCurrentMove); | 498 tremove(combinedMoves, numCurrentMove); |
| 495 end | 499 end |
| 496 end | 500 end |
| 497 | 501 |
| 498 -- Proceed with the next element (or previous considering we're going from last to first) | 502 -- Proceed with the next element (or previous considering we're going from last to first) |
| 499 numCurrentMove = (numCurrentMove - 1); | 503 numCurrentMove = (numCurrentMove - 1); |
| 547 self:CancelTimer(tmrProcessNext, true); -- silent | 551 self:CancelTimer(tmrProcessNext, true); -- silent |
| 548 | 552 |
| 549 self:UnregisterEvent("UI_ERROR_MESSAGE"); | 553 self:UnregisterEvent("UI_ERROR_MESSAGE"); |
| 550 | 554 |
| 551 -- Reset vars | 555 -- Reset vars |
| 552 table.wipe(combinedMoves); | 556 twipe(combinedMoves); |
| 553 movesSource = nil; | 557 movesSource = nil; |
| 554 if MailAddonBusy == addon:GetName() then | 558 if MailAddonBusy == addon:GetName() then |
| 555 MailAddonBusy = nil; | 559 MailAddonBusy = nil; |
| 556 end | 560 end |
| 557 end | 561 end |
