comparison Import.lua @ 161:35612aee8e15

Added junk list.
author yellowfive
date Mon, 06 May 2019 14:08:03 -0700
parents cc82eeeec1c8
children f27a7c64b21f
comparison
equal deleted inserted replaced
160:d670336e8c89 161:35612aee8e15
25 local function onTextEnterPressed(widget) 25 local function onTextEnterPressed(widget)
26 -- hide the overwolf cover when import data is received 26 -- hide the overwolf cover when import data is received
27 if _panelCover then 27 if _panelCover then
28 _panelCover:SetVisible(false) 28 _panelCover:SetVisible(false)
29 end 29 end
30 30
31 -- do an import if the data starts and ends with a dollar sign 31 -- do an import if the data starts with a dollar sign
32 local txt = _txtImport:GetText() 32 local txt = _txtImport:GetText()
33 local txtLen = string.len(txt) 33 local txtLen = string.len(txt)
34 if txtLen > 2 and string.sub(txt, 1, 1) == '$' then 34 if txtLen > 6 and (string.sub(txt, 1, 1) == '$' or string.sub(txt, 1, 5) == "_bib_" or string.sub(txt, 1, 6) == "_junk_") then
35 onImportOkClick() 35 onImportOkClick()
36 end 36 end
37 37
38 end 38 end
39 39
120 ---------------------------------------------------------------------------- 120 ----------------------------------------------------------------------------
121 -- Import Parsing 121 -- Import Parsing
122 ---------------------------------------------------------------------------- 122 ----------------------------------------------------------------------------
123 123
124 -- 124 --
125 -- Import a character, returning nil on success, otherwise an error message, import result stored in the db. 125 -- Helper to parse a list of items in the standard item list format.
126 -- 126 --
127 function Amr:ImportCharacter(data, isTest, isChild) 127 local function parseItemList(parts, startPos, endToken, hasSlot)
128 128
129 -- make sure all data is up to date before importing and get a local copy of player's current state
130 local currentPlayerData = self:ExportCharacter()
131
132 if data == nil or string.len(data) == 0 then
133 return L.ImportErrorEmpty
134 end
135
136 -- if multiple setups are included in the data, parse each individually, then quit
137 local specParts = { strsplit("\n", data) }
138 if #specParts > 1 then
139 -- clear out any previously-imported BiB setups when importing new ones (non-BiB will always be imported one at a time)
140 for i = #Amr.db.char.GearSetups, 1, -1 do
141 if Amr.db.char.GearSetups[i].IsBib then
142 table.remove(Amr.db.char.GearSetups, i)
143 end
144 end
145
146 for i = 1, #specParts do
147 if specParts[i] ~= "_bib_" then
148 local err = self:ImportCharacter(specParts[i], isTest, true)
149 if err ~= nil then
150 return err
151 end
152 end
153 end
154
155 -- ensure that all BiB setups are sorted to the top
156 local nonBib = {}
157 for i = #Amr.db.char.GearSetups, 1, -1 do
158 if not Amr.db.char.GearSetups[i].IsBib then
159 table.insert(nonBib, Amr.db.char.GearSetups[i])
160 table.remove(Amr.db.char.GearSetups, i)
161 end
162 end
163 for i, setup in ipairs(nonBib) do
164 table.insert(Amr.db.char.GearSetups, setup)
165 end
166
167 return
168 end
169
170 local data1 = { strsplit("$", data) }
171 if #data1 ~= 3 then
172 return L.ImportErrorFormat
173 end
174
175 local parts = { strsplit(";", data1[2]) }
176
177 -- require a minimum version
178 local ver = tonumber(parts[1])
179 if ver < Amr.MIN_IMPORT_VERSION then
180 return L.ImportErrorVersion
181 end
182
183 -- require name match (don't match realm due to language issues for now)
184 if not isTest then
185 local region = parts[2]
186 local realm = parts[3]
187 local name = parts[4]
188 if name ~= currentPlayerData.Name then
189 local importPlayerName = name .. " (" .. realm .. ")"
190 local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
191 return L.ImportErrorChar(importPlayerName, you)
192 end
193
194 -- require race match
195 local race = tonumber(parts[6])
196 if race ~= Amr.RaceIds[currentPlayerData.Race] then
197 return L.ImportErrorRace
198 end
199
200 -- require faction match
201 local faction = tonumber(parts[7])
202 if faction ~= Amr.FactionIds[currentPlayerData.Faction] then
203 return L.ImportErrorFaction
204 end
205
206 -- require level match
207 local level = tonumber(parts[8])
208 if level ~= currentPlayerData.Level then
209 return L.ImportErrorLevel
210 end
211 end
212
213 -- if we make it this far, the data is valid, so read item information
214 local specSlot = tonumber(parts[11])
215
216 local importData = {} 129 local importData = {}
217 local enchantInfo = {} 130
218
219 local prevItemId = 0 131 local prevItemId = 0
220 local prevGemId = 0 132 local prevGemId = 0
221 local prevEnchantId = 0 133 local prevEnchantId = 0
222 local prevUpgradeId = 0 134 local prevUpgradeId = 0
223 local prevBonusId = 0 135 local prevBonusId = 0
234 ["6"] = true, 146 ["6"] = true,
235 ["7"] = true, 147 ["7"] = true,
236 ["8"] = true, 148 ["8"] = true,
237 ["9"] = true, 149 ["9"] = true,
238 } 150 }
239 for i = 16, #parts do 151 for i = startPos, #parts do
240 local itemString = parts[i] 152 local itemString = parts[i]
241 if itemString ~= "" and itemString ~= "_" then 153 if itemString == endToken then
154 break
155 elseif itemString ~= "" and itemString ~= "_" then
242 local tokens = {} 156 local tokens = {}
243 local bonusIds = {} 157 local bonusIds = {}
244 local azerite = {} 158 local azerite = {}
245 local hasBonuses = false 159 local hasBonuses = false
246 local hasAzerites = false 160 local hasAzerites = false
297 prop = c 211 prop = c
298 end 212 end
299 end 213 end
300 214
301 local obj = {} 215 local obj = {}
302 importData[tonumber(tokens["s"])] = obj 216
303 217 if hasSlot then
218 importData[tonumber(tokens["s"])] = obj
219 else
220 table.insert(importData, obj)
221 end
222
304 obj.id = tokens["i"] 223 obj.id = tokens["i"]
305 obj.suffixId = tokens["f"] or 0 224 obj.suffixId = tokens["f"] or 0
306 obj.upgradeId = tokens["u"] or 0 225 obj.upgradeId = tokens["u"] or 0
307 obj.level = tokens["v"] or 0 226 obj.level = tokens["v"] or 0
308 obj.enchantId = tokens["e"] or 0 227 obj.enchantId = tokens["e"] or 0
321 if hasAzerites then 240 if hasAzerites then
322 obj.azerite = azerite 241 obj.azerite = azerite
323 end 242 end
324 end 243 end
325 end 244 end
245
246 return importData
247 end
248
249 --
250 -- Import a character, returning nil on success, otherwise an error message, import result stored in the db.
251 --
252 function Amr:ImportCharacter(data, isTest, isChild)
253
254 -- make sure all data is up to date before importing and get a local copy of player's current state
255 local currentPlayerData = self:ExportCharacter()
256
257 if data == nil or string.len(data) == 0 then
258 return L.ImportErrorEmpty
259 end
260
261 -- if multiple setups are included in the data, parse each individually, then quit
262 local specParts = { strsplit("\n", data) }
263
264 if #specParts > 1 and specParts[1] == "_junk_" then
265 -- if the string starts with "_junk_" then it is the junk list
266 Amr:ImportJunkList(specParts[2], currentPlayerData)
267 return
268
269 elseif #specParts > 1 then
270 -- clear out any previously-imported BiB setups when importing new ones (non-BiB will always be imported one at a time)
271 for i = #Amr.db.char.GearSetups, 1, -1 do
272 if Amr.db.char.GearSetups[i].IsBib then
273 table.remove(Amr.db.char.GearSetups, i)
274 end
275 end
276
277 for i = 1, #specParts do
278 if specParts[i] ~= "_bib_" then
279 local err = self:ImportCharacter(specParts[i], isTest, true)
280 if err ~= nil then
281 return err
282 end
283 end
284 end
285
286 -- ensure that all BiB setups are sorted to the top
287 local nonBib = {}
288 for i = #Amr.db.char.GearSetups, 1, -1 do
289 if not Amr.db.char.GearSetups[i].IsBib then
290 table.insert(nonBib, Amr.db.char.GearSetups[i])
291 table.remove(Amr.db.char.GearSetups, i)
292 end
293 end
294 for i, setup in ipairs(nonBib) do
295 table.insert(Amr.db.char.GearSetups, setup)
296 end
297
298 return
299 end
300
301 local data1 = { strsplit("$", data) }
302 if #data1 ~= 3 then
303 return L.ImportErrorFormat
304 end
305
306 local parts = { strsplit(";", data1[2]) }
307
308 -- require a minimum version
309 local ver = tonumber(parts[1])
310 if ver < Amr.MIN_IMPORT_VERSION then
311 return L.ImportErrorVersion
312 end
313
314 -- require name match (don't match realm due to language issues for now)
315 if not isTest then
316 local region = parts[2]
317 local realm = parts[3]
318 local name = parts[4]
319 if name ~= currentPlayerData.Name then
320 local importPlayerName = name .. " (" .. realm .. ")"
321 local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
322 return L.ImportErrorChar(importPlayerName, you)
323 end
324
325 -- require race match
326 local race = tonumber(parts[6])
327 if race ~= Amr.RaceIds[currentPlayerData.Race] then
328 return L.ImportErrorRace
329 end
330
331 -- require faction match
332 local faction = tonumber(parts[7])
333 if faction ~= Amr.FactionIds[currentPlayerData.Faction] then
334 return L.ImportErrorFaction
335 end
336
337 -- require level match
338 local level = tonumber(parts[8])
339 if level ~= currentPlayerData.Level then
340 return L.ImportErrorLevel
341 end
342 end
343
344 -- if we make it this far, the data is valid, so read item information
345 local specSlot = tonumber(parts[11])
346
347 local importData = parseItemList(parts, 16, "n/a", true)
326 348
327 -- extra information contains setup id, display label, then extra enchant info 349 -- extra information contains setup id, display label, then extra enchant info
328 parts = { strsplit("@", data1[3]) } 350 parts = { strsplit("@", data1[3]) }
329 351
330 local setupId = parts[2] 352 local setupId = parts[2]
331 local setupName = parts[3] 353 local setupName = parts[3]
354 local enchantInfo = {}
332 355
333 for i = 4, #parts do 356 for i = 4, #parts do
334 local infoParts = { strsplit("\\", parts[i]) } 357 local infoParts = { strsplit("\\", parts[i]) }
335 358
336 if infoParts[1] == "e" then 359 if infoParts[1] == "e" then
408 431
409 -- also update shopping list after import 432 -- also update shopping list after import
410 Amr:UpdateShoppingData(currentPlayerData) 433 Amr:UpdateShoppingData(currentPlayerData)
411 end 434 end
412 end 435 end
436
437 --
438 -- Import a list of items that are junk.
439 --
440 function Amr:ImportJunkList(data, currentPlayerData)
441
442 local data1 = { strsplit("$", data) }
443 if #data1 ~= 3 then
444 return L.ImportErrorFormat
445 end
446
447 local parts = { strsplit(";", data1[2]) }
448
449 -- require a minimum version
450 local ver = tonumber(parts[1])
451 if ver < Amr.MIN_IMPORT_VERSION then
452 return L.ImportErrorVersion
453 end
454
455 -- require name match
456 local region = parts[2]
457 local realm = parts[3]
458 local name = parts[4]
459 if name ~= currentPlayerData.Name then
460 local importPlayerName = name .. " (" .. realm .. ")"
461 local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
462 return L.ImportErrorChar(importPlayerName, you)
463 end
464
465 local keepStartPos = 0
466 local junkStartPos = 0
467 for i = 5, #parts do
468 local partString = parts[i]
469 if partString == ".k" then
470 keepStartPos = i + 1
471 elseif partString == ".d" then
472 junkStartPos = i + 1
473 end
474 end
475
476 Amr.db.char.JunkData = {}
477
478 -- Keep is a lookup by unique id
479 local keep = parseItemList(parts, keepStartPos, ".d", false)
480 Amr.db.char.JunkData.Keep = {}
481 for i = 1, #keep do
482 local uniqueId = Amr.GetItemUniqueId(keep[i])
483 Amr.db.char.JunkData.Keep[uniqueId] = keep[i]
484 end
485
486 -- Junk is a simple list of items to discard, in the desired display order
487 Amr.db.char.JunkData.Junk = parseItemList(parts, junkStartPos, "n/a", false)
488
489 -- extra information contains extra enchant info
490 if #data1 >= 3 then
491 parts = { strsplit("@", data1[3]) }
492
493 local enchantInfo = {}
494
495 for i = 2, #parts do
496 local infoParts = { strsplit("\\", parts[i]) }
497
498 if infoParts[1] == "e" then
499
500 local enchObj = {}
501 enchObj.id = tonumber(infoParts[2])
502 enchObj.itemId = tonumber(infoParts[3])
503 enchObj.spellId = tonumber(infoParts[4])
504 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end)
505
506 local mats = infoParts[6]
507 if string.len(mats) > 0 then
508 enchObj.materials = {}
509 mats = { strsplit(",", mats) }
510 for j = 1, #mats do
511 local kv = { strsplit("=", mats[j]) }
512 enchObj.materials[tonumber(kv[1])] = tonumber(kv[2])
513 end
514 end
515
516 enchantInfo[enchObj.id] = enchObj
517 end
518 end
519
520 for k,v in pairs(enchantInfo) do
521 Amr.db.char.ExtraEnchantData[k] = v
522 end
523 end
524
525 -- show the junk window after a successful junk import
526 Amr:ShowJunkWindow()
527 end