Skip to content

Commit e82bad5

Browse files
authored
Rewrite item link parsing code, fixing unstackable stacks. (#657)
* Fixed CURSOR_UPDATE/CHANGED errors. * Rewrote item-deduplication for all versions, merging unstackable items should now work again.
1 parent f7c82c3 commit e82bad5

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

core/Constants.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ local L = addon.L
2626
addon.isRetail = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
2727
addon.isClassic = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
2828
addon.isBCC = WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC and LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_BURNING_CRUSADE
29-
addon.isWrath = WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC and LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_NORTHREND
29+
addon.isWrath = WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC and LE_EXPANSION_LEVEL_CURRENT == LE_EXPANSION_WRATH_OF_THE_LICH_KING
3030

3131
--<GLOBALS
3232
local _G = _G

core/Utility.lua

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ local setmetatable = _G.setmetatable
5151
local strjoin = _G.strjoin
5252
local strmatch = _G.strmatch
5353
local strsplit = _G.strsplit
54+
local strsplittable = _G.strsplittable
5455
local tonumber = _G.tonumber
5556
local tostring = _G.tostring
5657
local type = _G.type
@@ -170,6 +171,88 @@ function addon.IsValidItemLink(link)
170171
end
171172
end
172173

174+
-- ParseItemLink parses an item link for it's distinct attributes and
175+
-- returns a table with every attribute. Updated as of retail 9.2.7.
176+
function addon.ParseItemLink(link)
177+
-- Parse the first elements that have no variable length
178+
local _, itemID, enchantID, gemID1, gemID2, gemID3, gemID4,
179+
suffixID, uniqueID, linkLevel, specializationID, modifiersMask,
180+
itemContext, rest = strsplit(":", link, 14)
181+
182+
-- The next several link items have a variable length and must be parsed
183+
-- out one by one. There is definitely a more clever way of doing this,
184+
-- but we want to optimize for readability. Blizzard has upended item links
185+
-- before, which would make this code diffcult to update if it's too "clever".
186+
local numBonusIDs
187+
local bonusIDs
188+
numBonusIDs, rest = strsplit(":", rest, 2)
189+
if numBonusIDs ~= "" then
190+
local splits = (tonumber(numBonusIDs))+1
191+
bonusIDs = strsplittable(":", rest, splits)
192+
rest = table.remove(bonusIDs, splits)
193+
end
194+
195+
local numModifiers
196+
local modifierIDs
197+
numModifiers, rest = strsplit(":", rest, 2)
198+
if numModifiers ~= "" then
199+
local splits = (tonumber(numModifiers)*2)+1
200+
modifierIDs = strsplittable(":", rest, splits)
201+
rest = table.remove(modifierIDs, splits)
202+
end
203+
204+
local relic1NumBonusIDs
205+
local relic1BonusIDs
206+
relic1NumBonusIDs, rest = strsplit(":", rest, 2)
207+
if relic1NumBonusIDs ~= "" then
208+
local splits = (tonumber(relic1NumBonusIDs))+1
209+
relic1BonusIDs = strsplittable(":", rest, splits)
210+
rest = table.remove(relic1BonusIDs, splits)
211+
end
212+
213+
local relic2NumBonusIDs
214+
local relic2BonusIDs
215+
relic2NumBonusIDs, rest = strsplit(":", rest, 2)
216+
if relic2NumBonusIDs ~= "" then
217+
local splits = (tonumber(relic2NumBonusIDs))+1
218+
relic2BonusIDs = strsplittable(":", rest, (tonumber(relic2NumBonusIDs))+1)
219+
rest = table.remove(relic2BonusIDs, splits)
220+
end
221+
222+
local relic3NumBonusIDs
223+
local relic3BonusIDs
224+
relic3NumBonusIDs, rest = strsplit(":", rest, 2)
225+
if relic3NumBonusIDs ~= "" then
226+
local splits = (tonumber(relic3NumBonusIDs))+1
227+
relic3BonusIDs = strsplittable(":", rest, (tonumber(relic3NumBonusIDs))+1)
228+
rest = table.remove(relic3BonusIDs, splits)
229+
end
230+
231+
local crafterGUID, extraEnchantID = strsplit(":", rest, 3)
232+
233+
return {
234+
itemID = itemID,
235+
enchantID = enchantID,
236+
gemID1 = gemID1,
237+
gemID2 = gemID2,
238+
gemID3 = gemID3,
239+
gemID4 = gemID4,
240+
suffixID = suffixID,
241+
uniqueID = uniqueID,
242+
linkLevel = linkLevel,
243+
specializationID = specializationID,
244+
modifiersMask = modifiersMask,
245+
itemContext = itemContext,
246+
bonusIDs = bonusIDs or {},
247+
modifierIDs = modifierIDs or {},
248+
relic1BonusIDs = relic1BonusIDs or {},
249+
relic2BonusIDs = relic2BonusIDs or {},
250+
relic3BonusIDs = relic3BonusIDs or {},
251+
crafterGUID = crafterGUID,
252+
extraEnchantID = extraEnchantID
253+
}
254+
end
255+
173256
--------------------------------------------------------------------------------
174257
-- Get distinct item IDs from item links
175258
--------------------------------------------------------------------------------
@@ -179,15 +262,29 @@ local function __GetDistinctItemID(link)
179262
if strmatch(link, "battlepet:") or strmatch(link, "keystone:") then
180263
return link
181264
else
182-
local itemString, id, enchant, gem1, gem2, gem3, gem4, suffix, reforge = strmatch(link, '(item:(%-?%d+):(%-?%d+):(%-?%d+):(%-?%d+):(%-?%d+):(%-?%d+):(%-?%d+):%-?%d+:%-?%d+:(%-?%d+))')
183-
if not id then return end
184-
id = tonumber(id)
265+
local itemData = addon.ParseItemLink(link)
266+
if not itemData then return end
267+
local newLink
268+
local id = tonumber(itemData.itemID)
185269
local equipSlot = select(9, GetItemInfo(id))
186270
if equipSlot and equipSlot ~= "" and equipSlot ~= "INVTYPE_BAG" then
187-
-- Rebuild an item link without noise
188-
id = strjoin(':', 'item', id, enchant, gem1, gem2, gem3, gem4, suffix, "0", "0", reforge)
271+
-- Rebuild an item link without any unique identifiers that are out of the player's control.
272+
newLink = strjoin(':', '|Hitem',
273+
itemData.itemID, itemData.enchantID, itemData.gemID1, itemData.gemID2, itemData.gemID3, itemData.gemID4,
274+
itemData.suffixID, itemData.uniqueID, itemData.linkLevel, itemData.specializationID,
275+
itemData.modifiersMask, itemData.itemContext,
276+
#itemData.bonusIDs,
277+
table.concat(itemData.bonusIDs, ":"),
278+
#itemData.modifierIDs,
279+
table.concat(itemData.modifierIDs),
280+
"", -- Relic 1
281+
"", -- Relic 2
282+
"", -- Relic 3
283+
"", -- Crafter GUID
284+
itemData.extraEnchantID or "" -- Fix for non-retail.
285+
)
189286
end
190-
return id
287+
return newLink
191288
end
192289
end
193290

modules/FilterOverride.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ end
115115

116116
function mod:OnEnable()
117117
self:UpdateOptions()
118-
self:RegisterEvent('CURSOR_CHANGED')
118+
if addon.isRetail or addon.isWrath then
119+
self:RegisterEvent('CURSOR_CHANGED')
120+
else
121+
self:RegisterEvent('CURSOR_UPDATE', 'CURSOR_CHANGED')
122+
end
119123
addon.RegisterSectionHeaderScript(self, 'OnTooltipUpdate', 'OnTooltipUpdateSectionHeader')
120124
addon.RegisterSectionHeaderScript(self, 'OnClick', 'OnClickSectionHeader')
121125
self:CURSOR_CHANGED()

0 commit comments

Comments
 (0)