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 |