| 
yellowfive@57
 | 
     1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot")
 | 
| 
yellowfive@57
 | 
     2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true)
 | 
| 
yellowfive@57
 | 
     3 local AceGUI = LibStub("AceGUI-3.0")
 | 
| 
yellowfive@57
 | 
     4 
 | 
| 
yellowfive@57
 | 
     5 local _txtImport
 | 
| 
yellowfive@57
 | 
     6 local _lblError
 | 
| 
yellowfive@69
 | 
     7 local _panelCover
 | 
| 
yellowfive@57
 | 
     8 
 | 
| 
yellowfive@57
 | 
     9 local function onImportOkClick(widget)
 | 
| 
yellowfive@57
 | 
    10 	local txt = _txtImport:GetText()
 | 
| 
yellowfive@57
 | 
    11 	local msg = Amr:ImportCharacter(txt)
 | 
| 
yellowfive@57
 | 
    12 	if msg then
 | 
| 
yellowfive@57
 | 
    13 		_lblError:SetText(msg)
 | 
| 
yellowfive@57
 | 
    14 		_txtImport:SetFocus(true)
 | 
| 
yellowfive@57
 | 
    15 	else
 | 
| 
yellowfive@57
 | 
    16 		Amr:HideCover()
 | 
| 
yellowfive@139
 | 
    17 		Amr:RefreshGearDisplay()
 | 
| 
yellowfive@57
 | 
    18 	end
 | 
| 
yellowfive@57
 | 
    19 end
 | 
| 
yellowfive@57
 | 
    20 
 | 
| 
yellowfive@57
 | 
    21 local function onImportCancelClick(widget)
 | 
| 
yellowfive@57
 | 
    22 	Amr:HideCover()
 | 
| 
yellowfive@57
 | 
    23 end
 | 
| 
yellowfive@57
 | 
    24 
 | 
| 
yellowfive@69
 | 
    25 local function onTextEnterPressed(widget)
 | 
| 
yellowfive@69
 | 
    26 	-- hide the overwolf cover when import data is received
 | 
| 
yellowfive@69
 | 
    27 	if _panelCover then
 | 
| 
yellowfive@69
 | 
    28 		_panelCover:SetVisible(false)
 | 
| 
yellowfive@69
 | 
    29 	end
 | 
| 
yellowfive@161
 | 
    30     
 | 
| 
yellowfive@161
 | 
    31 	-- do an import if the data starts with a dollar sign
 | 
| 
yellowfive@161
 | 
    32     local txt = _txtImport:GetText()
 | 
| 
yellowfive@69
 | 
    33 	local txtLen = string.len(txt)
 | 
| 
yellowfive@161
 | 
    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
 | 
| 
yellowfive@69
 | 
    35 		onImportOkClick()
 | 
| 
yellowfive@69
 | 
    36 	end
 | 
| 
yellowfive@69
 | 
    37 	
 | 
| 
yellowfive@69
 | 
    38 end
 | 
| 
yellowfive@69
 | 
    39 
 | 
| 
yellowfive@69
 | 
    40 local function renderImportWindow(container, fromOverwolf)
 | 
| 
yellowfive@57
 | 
    41 
 | 
| 
yellowfive@57
 | 
    42 	local panelImport = Amr:RenderCoverChrome(container, 700, 450)
 | 
| 
yellowfive@57
 | 
    43 	
 | 
| 
yellowfive@57
 | 
    44 	local lbl = AceGUI:Create("AmrUiLabel")
 | 
| 
yellowfive@124
 | 
    45 	panelImport:AddChild(lbl)
 | 
| 
yellowfive@57
 | 
    46 	lbl:SetWidth(600)
 | 
| 
yellowfive@57
 | 
    47 	lbl:SetText(L.ImportHeader)
 | 
| 
yellowfive@57
 | 
    48 	lbl:SetPoint("TOP", panelImport.content, "TOP", 0, -10)
 | 
| 
yellowfive@57
 | 
    49 
 | 
| 
yellowfive@57
 | 
    50 	_txtImport = AceGUI:Create("AmrUiTextarea")
 | 
| 
yellowfive@57
 | 
    51 	_txtImport:SetWidth(600)
 | 
| 
yellowfive@57
 | 
    52 	_txtImport:SetHeight(300)
 | 
| 
yellowfive@57
 | 
    53 	_txtImport:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text))
 | 
| 
yellowfive@69
 | 
    54 	_txtImport:SetCallback("OnEnterPressed", onTextEnterPressed)
 | 
| 
yellowfive@57
 | 
    55 	panelImport:AddChild(_txtImport)
 | 
| 
yellowfive@124
 | 
    56 	_txtImport:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -10)
 | 
| 
yellowfive@57
 | 
    57 	
 | 
| 
yellowfive@57
 | 
    58 	local btnImportOk = AceGUI:Create("AmrUiButton")
 | 
| 
yellowfive@57
 | 
    59 	btnImportOk:SetText(L.ImportButtonOk)
 | 
| 
yellowfive@57
 | 
    60 	btnImportOk:SetBackgroundColor(Amr.Colors.Green)
 | 
| 
yellowfive@57
 | 
    61 	btnImportOk:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White))
 | 
| 
yellowfive@57
 | 
    62 	btnImportOk:SetWidth(120)
 | 
| 
yellowfive@57
 | 
    63 	btnImportOk:SetHeight(28)
 | 
| 
yellowfive@57
 | 
    64 	btnImportOk:SetCallback("OnClick", onImportOkClick)
 | 
| 
yellowfive@57
 | 
    65 	panelImport:AddChild(btnImportOk)
 | 
| 
yellowfive@124
 | 
    66 	btnImportOk:SetPoint("TOPLEFT", _txtImport.frame, "BOTTOMLEFT", 0, -10)
 | 
| 
yellowfive@57
 | 
    67 	
 | 
| 
yellowfive@57
 | 
    68 	local btnImportCancel = AceGUI:Create("AmrUiButton")
 | 
| 
yellowfive@57
 | 
    69 	btnImportCancel:SetText(L.ImportButtonCancel)
 | 
| 
yellowfive@57
 | 
    70 	btnImportCancel:SetBackgroundColor(Amr.Colors.Green)
 | 
| 
yellowfive@57
 | 
    71 	btnImportCancel:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White))
 | 
| 
yellowfive@57
 | 
    72 	btnImportCancel:SetWidth(120)
 | 
| 
yellowfive@57
 | 
    73 	btnImportCancel:SetHeight(28)
 | 
| 
yellowfive@57
 | 
    74 	btnImportCancel:SetCallback("OnClick", onImportCancelClick)
 | 
| 
yellowfive@57
 | 
    75 	panelImport:AddChild(btnImportCancel)
 | 
| 
yellowfive@124
 | 
    76 	btnImportCancel:SetPoint("LEFT", btnImportOk.frame, "RIGHT", 20, 0)
 | 
| 
yellowfive@57
 | 
    77 	
 | 
| 
yellowfive@57
 | 
    78 	_lblError = AceGUI:Create("AmrUiLabel")
 | 
| 
yellowfive@124
 | 
    79 	panelImport:AddChild(_lblError)
 | 
| 
yellowfive@57
 | 
    80 	_lblError:SetWidth(600)
 | 
| 
yellowfive@57
 | 
    81 	_lblError:SetFont(Amr.CreateFont("Bold", 14, Amr.Colors.Red))
 | 
| 
yellowfive@57
 | 
    82 	_lblError:SetText("")
 | 
| 
yellowfive@57
 | 
    83 	_lblError:SetPoint("TOPLEFT", btnImportOk.frame, "BOTTOMLEFT", 0, -20)
 | 
| 
yellowfive@57
 | 
    84 	
 | 
| 
yellowfive@69
 | 
    85 	if fromOverwolf then
 | 
| 
yellowfive@69
 | 
    86 		-- show a cover preventing interaction until we receive data from overwolf
 | 
| 
yellowfive@69
 | 
    87 		_panelCover = AceGUI:Create("AmrUiPanel")
 | 
| 
yellowfive@69
 | 
    88 		_panelCover:SetLayout("None")
 | 
| 
yellowfive@69
 | 
    89 		_panelCover:EnableMouse(true)
 | 
| 
yellowfive@69
 | 
    90 		_panelCover:SetBackgroundColor(Amr.Colors.Black, 0.75)
 | 
| 
yellowfive@124
 | 
    91 		panelImport:AddChild(_panelCover)
 | 
| 
yellowfive@69
 | 
    92 		_panelCover:SetPoint("TOPLEFT", panelImport.frame, "TOPLEFT")
 | 
| 
yellowfive@69
 | 
    93 		_panelCover:SetPoint("BOTTOMRIGHT", panelImport.frame, "BOTTOMRIGHT")
 | 
| 
yellowfive@69
 | 
    94 
 | 
| 
yellowfive@69
 | 
    95 		local coverMsg = AceGUI:Create("AmrUiLabel")
 | 
| 
yellowfive@124
 | 
    96 		_panelCover:AddChild(coverMsg)
 | 
| 
yellowfive@69
 | 
    97 		coverMsg:SetWidth(500)
 | 
| 
yellowfive@69
 | 
    98 		coverMsg:SetFont(Amr.CreateFont("Regular", 16, Amr.Colors.TextTan))
 | 
| 
yellowfive@69
 | 
    99 		coverMsg:SetJustifyH("MIDDLE")
 | 
| 
yellowfive@69
 | 
   100 		coverMsg:SetJustifyV("MIDDLE")
 | 
| 
yellowfive@69
 | 
   101 		coverMsg:SetText(L.ImportOverwolfWait)
 | 
| 
yellowfive@69
 | 
   102 		coverMsg:SetPoint("CENTER", _panelCover.frame, "CENTER", 0, 20)
 | 
| 
yellowfive@69
 | 
   103 		
 | 
| 
yellowfive@69
 | 
   104 		-- after adding, set cover to sit on top of everything
 | 
| 
yellowfive@69
 | 
   105 		_panelCover:SetStrata("FULLSCREEN_DIALOG")
 | 
| 
yellowfive@69
 | 
   106 		_panelCover:SetLevel(Amr.FrameLevels.Highest)		
 | 
| 
yellowfive@69
 | 
   107 	end
 | 
| 
yellowfive@57
 | 
   108 end
 | 
| 
yellowfive@57
 | 
   109 
 | 
| 
yellowfive@69
 | 
   110 function Amr:ShowImportWindow(fromOverwolf)
 | 
| 
yellowfive@57
 | 
   111 	-- this is shown as a modal dialog
 | 
| 
yellowfive@69
 | 
   112 	Amr:ShowCover(function(container)
 | 
| 
yellowfive@69
 | 
   113 		renderImportWindow(container, fromOverwolf)
 | 
| 
yellowfive@69
 | 
   114 	end)
 | 
| 
yellowfive@57
 | 
   115 	
 | 
| 
yellowfive@57
 | 
   116 	_txtImport:SetText("")
 | 
| 
yellowfive@57
 | 
   117 	_txtImport:SetFocus(true)
 | 
| 
yellowfive@57
 | 
   118 end
 | 
| 
yellowfive@57
 | 
   119 
 | 
| 
yellowfive@57
 | 
   120 ----------------------------------------------------------------------------
 | 
| 
yellowfive@57
 | 
   121 -- Import Parsing
 | 
| 
yellowfive@57
 | 
   122 ----------------------------------------------------------------------------
 | 
| 
yellowfive@57
 | 
   123 
 | 
| 
yellowfive@57
 | 
   124 --
 | 
| 
yellowfive@161
 | 
   125 -- Helper to parse a list of items in the standard item list format.
 | 
| 
yellowfive@161
 | 
   126 --
 | 
| 
yellowfive@161
 | 
   127 local function parseItemList(parts, startPos, endToken, hasSlot)
 | 
| 
yellowfive@161
 | 
   128 
 | 
| 
yellowfive@161
 | 
   129     local importData = {}
 | 
| 
yellowfive@161
 | 
   130 
 | 
| 
yellowfive@161
 | 
   131     local prevItemId = 0
 | 
| 
yellowfive@161
 | 
   132     local prevGemId = 0
 | 
| 
yellowfive@161
 | 
   133     local prevEnchantId = 0
 | 
| 
yellowfive@161
 | 
   134     local prevUpgradeId = 0
 | 
| 
yellowfive@161
 | 
   135     local prevBonusId = 0
 | 
| 
yellowfive@161
 | 
   136     local prevLevel = 0
 | 
| 
yellowfive@185
 | 
   137     --local prevAzeriteId = 0
 | 
| 
yellowfive@161
 | 
   138     local digits = {
 | 
| 
yellowfive@161
 | 
   139         ["-"] = true,
 | 
| 
yellowfive@161
 | 
   140         ["0"] = true,
 | 
| 
yellowfive@161
 | 
   141         ["1"] = true,
 | 
| 
yellowfive@161
 | 
   142         ["2"] = true,
 | 
| 
yellowfive@161
 | 
   143         ["3"] = true,
 | 
| 
yellowfive@161
 | 
   144         ["4"] = true,
 | 
| 
yellowfive@161
 | 
   145         ["5"] = true,
 | 
| 
yellowfive@161
 | 
   146         ["6"] = true,
 | 
| 
yellowfive@161
 | 
   147         ["7"] = true,
 | 
| 
yellowfive@161
 | 
   148         ["8"] = true,
 | 
| 
yellowfive@161
 | 
   149         ["9"] = true,
 | 
| 
yellowfive@161
 | 
   150     }
 | 
| 
yellowfive@161
 | 
   151     for i = startPos, #parts do
 | 
| 
yellowfive@161
 | 
   152         local itemString = parts[i]
 | 
| 
yellowfive@161
 | 
   153         if itemString == endToken then
 | 
| 
yellowfive@161
 | 
   154             break
 | 
| 
yellowfive@161
 | 
   155         elseif itemString ~= "" and itemString ~= "_" then
 | 
| 
yellowfive@161
 | 
   156             local tokens = {}
 | 
| 
yellowfive@161
 | 
   157             local bonusIds = {}
 | 
| 
yellowfive@185
 | 
   158             --local azerite = {}
 | 
| 
yellowfive@161
 | 
   159             local hasBonuses = false
 | 
| 
yellowfive@185
 | 
   160             --local hasAzerites = false
 | 
| 
yellowfive@161
 | 
   161             local token = ""
 | 
| 
yellowfive@161
 | 
   162             local prop = "i"
 | 
| 
yellowfive@161
 | 
   163             local tokenComplete = false
 | 
| 
yellowfive@161
 | 
   164             for j = 1, string.len(itemString) do
 | 
| 
yellowfive@161
 | 
   165                 local c = string.sub(itemString, j, j)
 | 
| 
yellowfive@161
 | 
   166                 if digits[c] == nil then
 | 
| 
yellowfive@161
 | 
   167                     tokenComplete = true
 | 
| 
yellowfive@161
 | 
   168                 else
 | 
| 
yellowfive@161
 | 
   169                     token = token .. c
 | 
| 
yellowfive@161
 | 
   170                 end
 | 
| 
yellowfive@161
 | 
   171                 
 | 
| 
yellowfive@161
 | 
   172                 if tokenComplete or j == string.len(itemString) then
 | 
| 
yellowfive@161
 | 
   173                     local val = tonumber(token)
 | 
| 
yellowfive@161
 | 
   174                     if prop == "i" then
 | 
| 
yellowfive@161
 | 
   175                         val = val + prevItemId
 | 
| 
yellowfive@161
 | 
   176                         prevItemId = val
 | 
| 
yellowfive@161
 | 
   177                     elseif prop == "u" then
 | 
| 
yellowfive@161
 | 
   178                         val = val + prevUpgradeId
 | 
| 
yellowfive@161
 | 
   179                         prevUpgradeId = val
 | 
| 
yellowfive@161
 | 
   180 					elseif prop == "v" then
 | 
| 
yellowfive@161
 | 
   181 						val = val + prevLevel
 | 
| 
yellowfive@161
 | 
   182 						prevLevel = val
 | 
| 
yellowfive@161
 | 
   183                     elseif prop == "b" then
 | 
| 
yellowfive@161
 | 
   184                         val = val + prevBonusId
 | 
| 
yellowfive@161
 | 
   185                         prevBonusId = val
 | 
| 
yellowfive@161
 | 
   186                     elseif prop == "x" or prop == "y" or prop == "z" then
 | 
| 
yellowfive@161
 | 
   187                         val = val + prevGemId
 | 
| 
yellowfive@161
 | 
   188                         prevGemId = val
 | 
| 
yellowfive@161
 | 
   189                     elseif prop == "e" then
 | 
| 
yellowfive@161
 | 
   190                         val = val + prevEnchantId
 | 
| 
yellowfive@161
 | 
   191                         prevEnchantId = val
 | 
| 
yellowfive@185
 | 
   192                     --elseif prop == "a" then
 | 
| 
yellowfive@185
 | 
   193                     --    val = val + prevAzeriteId
 | 
| 
yellowfive@185
 | 
   194                     --    prevAzeriteId = val
 | 
| 
yellowfive@161
 | 
   195                     end
 | 
| 
yellowfive@161
 | 
   196                     
 | 
| 
yellowfive@161
 | 
   197                     if prop == "b" then
 | 
| 
yellowfive@161
 | 
   198                         table.insert(bonusIds, val)
 | 
| 
yellowfive@161
 | 
   199                         hasBonuses = true
 | 
| 
yellowfive@185
 | 
   200                     --elseif prop == "a" then
 | 
| 
yellowfive@185
 | 
   201                     --    table.insert(azerite, val)
 | 
| 
yellowfive@185
 | 
   202                     --    hasAzerites = true
 | 
| 
yellowfive@161
 | 
   203                     else
 | 
| 
yellowfive@161
 | 
   204                         tokens[prop] = val
 | 
| 
yellowfive@161
 | 
   205                     end
 | 
| 
yellowfive@161
 | 
   206                     
 | 
| 
yellowfive@161
 | 
   207                     token = ""
 | 
| 
yellowfive@161
 | 
   208                     tokenComplete = false
 | 
| 
yellowfive@161
 | 
   209                     
 | 
| 
yellowfive@161
 | 
   210                     -- we have moved on to the next token
 | 
| 
yellowfive@161
 | 
   211                     prop = c
 | 
| 
yellowfive@161
 | 
   212                 end
 | 
| 
yellowfive@161
 | 
   213             end
 | 
| 
yellowfive@161
 | 
   214             
 | 
| 
yellowfive@161
 | 
   215             local obj = {}
 | 
| 
yellowfive@161
 | 
   216 
 | 
| 
yellowfive@161
 | 
   217             if hasSlot then
 | 
| 
yellowfive@161
 | 
   218                 importData[tonumber(tokens["s"])] = obj
 | 
| 
yellowfive@161
 | 
   219             else
 | 
| 
yellowfive@161
 | 
   220                 table.insert(importData, obj)
 | 
| 
yellowfive@161
 | 
   221             end
 | 
| 
yellowfive@161
 | 
   222 
 | 
| 
yellowfive@161
 | 
   223             obj.id = tokens["i"]
 | 
| 
yellowfive@161
 | 
   224             obj.suffixId = tokens["f"] or 0
 | 
| 
yellowfive@161
 | 
   225             obj.upgradeId = tokens["u"] or 0
 | 
| 
yellowfive@161
 | 
   226 			obj.level = tokens["v"] or 0
 | 
| 
yellowfive@161
 | 
   227             obj.enchantId = tokens["e"] or 0
 | 
| 
yellowfive@161
 | 
   228 			obj.inventoryId = tokens["t"] or 0
 | 
| 
yellowfive@161
 | 
   229             
 | 
| 
yellowfive@161
 | 
   230             obj.gemIds = {}
 | 
| 
yellowfive@161
 | 
   231             table.insert(obj.gemIds, tokens["x"] or 0)
 | 
| 
yellowfive@161
 | 
   232             table.insert(obj.gemIds, tokens["y"] or 0)
 | 
| 
yellowfive@161
 | 
   233             table.insert(obj.gemIds, tokens["z"] or 0)
 | 
| 
yellowfive@161
 | 
   234             table.insert(obj.gemIds, 0)
 | 
| 
yellowfive@161
 | 
   235             
 | 
| 
yellowfive@161
 | 
   236             if hasBonuses then
 | 
| 
yellowfive@161
 | 
   237                 obj.bonusIds = bonusIds
 | 
| 
yellowfive@161
 | 
   238             end
 | 
| 
yellowfive@161
 | 
   239             
 | 
| 
yellowfive@185
 | 
   240             --if hasAzerites then
 | 
| 
yellowfive@185
 | 
   241             --    obj.azerite = azerite
 | 
| 
yellowfive@185
 | 
   242             --end
 | 
| 
yellowfive@161
 | 
   243         end
 | 
| 
yellowfive@161
 | 
   244     end
 | 
| 
yellowfive@161
 | 
   245 
 | 
| 
yellowfive@161
 | 
   246     return importData
 | 
| 
yellowfive@161
 | 
   247 end
 | 
| 
yellowfive@161
 | 
   248 
 | 
| 
yellowfive@185
 | 
   249 --[[
 | 
| 
yellowfive@165
 | 
   250 local function parseEssenceList(essenceString)
 | 
| 
yellowfive@165
 | 
   251     local ret = {}
 | 
| 
yellowfive@165
 | 
   252 
 | 
| 
yellowfive@165
 | 
   253     local parts = { strsplit("_", essenceString) }
 | 
| 
yellowfive@165
 | 
   254     for i = 1, #parts do
 | 
| 
yellowfive@165
 | 
   255         local essence = { strsplit(".", parts[i]) }
 | 
| 
yellowfive@181
 | 
   256         table.insert(ret, { tonumber(essence[1]), tonumber(essence[2]), tonumber(essence[3]) })
 | 
| 
yellowfive@165
 | 
   257     end
 | 
| 
yellowfive@165
 | 
   258 
 | 
| 
yellowfive@165
 | 
   259     return ret
 | 
| 
yellowfive@165
 | 
   260 end
 | 
| 
yellowfive@185
 | 
   261 ]]
 | 
| 
yellowfive@185
 | 
   262 
 | 
| 
yellowfive@185
 | 
   263 local function parseSoulbinds(soulbindString)
 | 
| 
yellowfive@185
 | 
   264     local ret = {}
 | 
| 
yellowfive@185
 | 
   265 
 | 
| 
yellowfive@185
 | 
   266     local parts = { strsplit(",", soulbindString) }
 | 
| 
yellowfive@185
 | 
   267     for i = 1, #parts do
 | 
| 
yellowfive@185
 | 
   268         local node = { strsplit(".", parts[i]) }
 | 
| 
yellowfive@185
 | 
   269         table.insert(ret, { tonumber(node[1]), tonumber(node[2]), tonumber(node[3]) })
 | 
| 
yellowfive@185
 | 
   270     end
 | 
| 
yellowfive@185
 | 
   271 
 | 
| 
yellowfive@185
 | 
   272     return ret
 | 
| 
yellowfive@185
 | 
   273 end
 | 
| 
yellowfive@165
 | 
   274 
 | 
| 
yellowfive@161
 | 
   275 --
 | 
| 
yellowfive@57
 | 
   276 -- Import a character, returning nil on success, otherwise an error message, import result stored in the db.
 | 
| 
yellowfive@57
 | 
   277 --
 | 
| 
yellowfive@139
 | 
   278 function Amr:ImportCharacter(data, isTest, isChild)
 | 
| 
yellowfive@57
 | 
   279 
 | 
| 
yellowfive@57
 | 
   280     -- make sure all data is up to date before importing and get a local copy of player's current state
 | 
| 
yellowfive@57
 | 
   281     local currentPlayerData = self:ExportCharacter()
 | 
| 
yellowfive@57
 | 
   282     
 | 
| 
yellowfive@57
 | 
   283     if data == nil or string.len(data) == 0 then
 | 
| 
yellowfive@57
 | 
   284         return L.ImportErrorEmpty
 | 
| 
yellowfive@57
 | 
   285     end
 | 
| 
yellowfive@161
 | 
   286     
 | 
| 
yellowfive@139
 | 
   287 	-- if multiple setups are included in the data, parse each individually, then quit
 | 
| 
yellowfive@161
 | 
   288     local specParts = { strsplit("\n", data) }
 | 
| 
yellowfive@161
 | 
   289     
 | 
| 
yellowfive@161
 | 
   290     if #specParts > 1 and specParts[1] == "_junk_" then
 | 
| 
yellowfive@161
 | 
   291         -- if the string starts with "_junk_" then it is the junk list
 | 
| 
yellowfive@165
 | 
   292         return Amr:ImportJunkList(specParts[2], currentPlayerData)
 | 
| 
yellowfive@161
 | 
   293 
 | 
| 
yellowfive@161
 | 
   294     elseif #specParts > 1 then
 | 
| 
yellowfive@139
 | 
   295         -- clear out any previously-imported BiB setups when importing new ones (non-BiB will always be imported one at a time)
 | 
| 
yellowfive@139
 | 
   296         for i = #Amr.db.char.GearSetups, 1, -1 do
 | 
| 
yellowfive@139
 | 
   297             if Amr.db.char.GearSetups[i].IsBib then
 | 
| 
yellowfive@139
 | 
   298                 table.remove(Amr.db.char.GearSetups, i)
 | 
| 
yellowfive@139
 | 
   299             end
 | 
| 
yellowfive@139
 | 
   300         end
 | 
| 
yellowfive@139
 | 
   301 
 | 
| 
yellowfive@141
 | 
   302         for i = 1, #specParts do
 | 
| 
yellowfive@141
 | 
   303             if specParts[i] ~= "_bib_" then
 | 
| 
yellowfive@141
 | 
   304                 local err = self:ImportCharacter(specParts[i], isTest, true)
 | 
| 
yellowfive@141
 | 
   305                 if err ~= nil then
 | 
| 
yellowfive@141
 | 
   306                     return err
 | 
| 
yellowfive@141
 | 
   307                 end
 | 
| 
yellowfive@141
 | 
   308             end
 | 
| 
yellowfive@139
 | 
   309         end
 | 
| 
yellowfive@139
 | 
   310         
 | 
| 
yellowfive@139
 | 
   311         -- ensure that all BiB setups are sorted to the top
 | 
| 
yellowfive@139
 | 
   312         local nonBib = {}
 | 
| 
yellowfive@139
 | 
   313         for i = #Amr.db.char.GearSetups, 1, -1 do
 | 
| 
yellowfive@139
 | 
   314             if not Amr.db.char.GearSetups[i].IsBib then
 | 
| 
yellowfive@139
 | 
   315                 table.insert(nonBib, Amr.db.char.GearSetups[i])
 | 
| 
yellowfive@139
 | 
   316                 table.remove(Amr.db.char.GearSetups, i)
 | 
| 
yellowfive@139
 | 
   317             end
 | 
| 
yellowfive@139
 | 
   318         end
 | 
| 
yellowfive@139
 | 
   319         for i, setup in ipairs(nonBib) do
 | 
| 
yellowfive@139
 | 
   320             table.insert(Amr.db.char.GearSetups, setup)
 | 
| 
yellowfive@139
 | 
   321         end
 | 
| 
yellowfive@139
 | 
   322 
 | 
| 
yellowfive@139
 | 
   323         return
 | 
| 
yellowfive@57
 | 
   324 	end
 | 
| 
yellowfive@57
 | 
   325     
 | 
| 
yellowfive@57
 | 
   326     local data1 = { strsplit("$", data) }
 | 
| 
yellowfive@57
 | 
   327     if #data1 ~= 3 then
 | 
| 
yellowfive@57
 | 
   328         return L.ImportErrorFormat
 | 
| 
yellowfive@57
 | 
   329     end
 | 
| 
yellowfive@57
 | 
   330     
 | 
| 
yellowfive@57
 | 
   331     local parts = { strsplit(";", data1[2]) }
 | 
| 
yellowfive@57
 | 
   332     
 | 
| 
yellowfive@57
 | 
   333     -- require a minimum version
 | 
| 
yellowfive@57
 | 
   334     local ver = tonumber(parts[1])
 | 
| 
yellowfive@57
 | 
   335     if ver < Amr.MIN_IMPORT_VERSION then
 | 
| 
yellowfive@57
 | 
   336         return L.ImportErrorVersion
 | 
| 
yellowfive@57
 | 
   337     end
 | 
| 
yellowfive@57
 | 
   338     
 | 
| 
yellowfive@57
 | 
   339     -- require name match (don't match realm due to language issues for now)
 | 
| 
yellowfive@57
 | 
   340     if not isTest then
 | 
| 
yellowfive@57
 | 
   341 		local region = parts[2]
 | 
| 
yellowfive@57
 | 
   342         local realm = parts[3]
 | 
| 
yellowfive@57
 | 
   343         local name = parts[4]
 | 
| 
yellowfive@57
 | 
   344         if name ~= currentPlayerData.Name then
 | 
| 
yellowfive@57
 | 
   345             local importPlayerName = name .. " (" .. realm .. ")"
 | 
| 
yellowfive@57
 | 
   346             local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
 | 
| 
yellowfive@57
 | 
   347             return L.ImportErrorChar(importPlayerName, you)
 | 
| 
yellowfive@57
 | 
   348         end
 | 
| 
yellowfive@57
 | 
   349         
 | 
| 
yellowfive@57
 | 
   350         -- require race match
 | 
| 
yellowfive@57
 | 
   351         local race = tonumber(parts[6])
 | 
| 
yellowfive@57
 | 
   352         if race ~= Amr.RaceIds[currentPlayerData.Race] then
 | 
| 
yellowfive@57
 | 
   353             return L.ImportErrorRace
 | 
| 
yellowfive@57
 | 
   354         end
 | 
| 
yellowfive@57
 | 
   355         
 | 
| 
yellowfive@57
 | 
   356         -- require faction match
 | 
| 
yellowfive@57
 | 
   357         local faction = tonumber(parts[7])
 | 
| 
yellowfive@57
 | 
   358         if faction ~= Amr.FactionIds[currentPlayerData.Faction] then
 | 
| 
yellowfive@57
 | 
   359             return L.ImportErrorFaction
 | 
| 
yellowfive@57
 | 
   360         end
 | 
| 
yellowfive@57
 | 
   361         
 | 
| 
yellowfive@57
 | 
   362         -- require level match
 | 
| 
yellowfive@57
 | 
   363         local level = tonumber(parts[8])
 | 
| 
yellowfive@57
 | 
   364         if level ~= currentPlayerData.Level then
 | 
| 
yellowfive@57
 | 
   365             return L.ImportErrorLevel
 | 
| 
yellowfive@57
 | 
   366         end
 | 
| 
yellowfive@57
 | 
   367     end
 | 
| 
yellowfive@57
 | 
   368     
 | 
| 
yellowfive@57
 | 
   369     -- if we make it this far, the data is valid, so read item information
 | 
| 
yellowfive@185
 | 
   370 	local specSlot = tonumber(parts[10])
 | 
| 
yellowfive@165
 | 
   371     
 | 
| 
yellowfive@185
 | 
   372     local soulbindId = tonumber(parts[14])
 | 
| 
yellowfive@185
 | 
   373     local soulbindNodes = parseSoulbinds(parts[15])
 | 
| 
yellowfive@185
 | 
   374     --local essences = parseEssenceList(parts[15])
 | 
| 
yellowfive@165
 | 
   375 
 | 
| 
yellowfive@165
 | 
   376     local importData = parseItemList(parts, 17, "n/a", true)
 | 
| 
yellowfive@57
 | 
   377     
 | 
| 
yellowfive@139
 | 
   378     -- extra information contains setup id, display label, then extra enchant info        
 | 
| 
yellowfive@57
 | 
   379     parts = { strsplit("@", data1[3]) }
 | 
| 
yellowfive@139
 | 
   380 
 | 
| 
yellowfive@139
 | 
   381     local setupId = parts[2]
 | 
| 
yellowfive@139
 | 
   382     local setupName = parts[3]
 | 
| 
yellowfive@161
 | 
   383     local enchantInfo = {}
 | 
| 
yellowfive@139
 | 
   384 
 | 
| 
yellowfive@139
 | 
   385     for i = 4, #parts do
 | 
| 
yellowfive@57
 | 
   386         local infoParts = { strsplit("\\", parts[i]) }
 | 
| 
yellowfive@57
 | 
   387         
 | 
| 
yellowfive@124
 | 
   388         if infoParts[1] == "e" then
 | 
| 
yellowfive@57
 | 
   389         
 | 
| 
yellowfive@57
 | 
   390             local enchObj = {}
 | 
| 
yellowfive@57
 | 
   391             enchObj.id = tonumber(infoParts[2])
 | 
| 
yellowfive@57
 | 
   392             enchObj.itemId = tonumber(infoParts[3])
 | 
| 
yellowfive@57
 | 
   393             enchObj.spellId = tonumber(infoParts[4])
 | 
| 
yellowfive@57
 | 
   394             enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end)
 | 
| 
yellowfive@57
 | 
   395             
 | 
| 
yellowfive@57
 | 
   396             local mats = infoParts[6]
 | 
| 
yellowfive@57
 | 
   397             if string.len(mats) > 0 then
 | 
| 
yellowfive@57
 | 
   398                 enchObj.materials = {}
 | 
| 
yellowfive@57
 | 
   399                 mats = { strsplit(",", mats) }
 | 
| 
yellowfive@57
 | 
   400                 for j = 1, #mats do
 | 
| 
yellowfive@57
 | 
   401                     local kv = { strsplit("=", mats[j]) }
 | 
| 
yellowfive@57
 | 
   402                     enchObj.materials[tonumber(kv[1])] = tonumber(kv[2])
 | 
| 
yellowfive@57
 | 
   403                 end
 | 
| 
yellowfive@57
 | 
   404             end
 | 
| 
yellowfive@57
 | 
   405             
 | 
| 
yellowfive@124
 | 
   406             enchantInfo[enchObj.id] = enchObj            
 | 
| 
yellowfive@57
 | 
   407         end
 | 
| 
yellowfive@57
 | 
   408     end
 | 
| 
yellowfive@57
 | 
   409     
 | 
| 
yellowfive@57
 | 
   410     if isTest then
 | 
| 
yellowfive@57
 | 
   411 		print("spec " .. specSlot)
 | 
| 
yellowfive@57
 | 
   412         -- print result for debugging
 | 
| 
yellowfive@57
 | 
   413         for k,v in pairs(importData) do
 | 
| 
yellowfive@57
 | 
   414 			local blah = Amr.CreateItemLink(v)
 | 
| 
yellowfive@57
 | 
   415 			--print(blah)
 | 
| 
yellowfive@57
 | 
   416             local name, link = GetItemInfo(blah)
 | 
| 
yellowfive@57
 | 
   417             print(link)
 | 
| 
yellowfive@57
 | 
   418             if link == nil then
 | 
| 
yellowfive@57
 | 
   419                 print(blah)
 | 
| 
yellowfive@57
 | 
   420                 print("bad item: " .. v.id)
 | 
| 
yellowfive@57
 | 
   421             end
 | 
| 
yellowfive@133
 | 
   422         end              
 | 
| 
yellowfive@57
 | 
   423     else
 | 
| 
yellowfive@57
 | 
   424         -- we have succeeded, record the result
 | 
| 
yellowfive@139
 | 
   425         local result = {
 | 
| 
yellowfive@139
 | 
   426             IsBib = string.sub(setupId, 1, 3) ~= "AMR",
 | 
| 
yellowfive@139
 | 
   427             SpecSlot = tonumber(specSlot),
 | 
| 
yellowfive@139
 | 
   428             Id = setupId,
 | 
| 
yellowfive@139
 | 
   429             Label = setupName,
 | 
| 
yellowfive@165
 | 
   430             Gear = importData,
 | 
| 
yellowfive@185
 | 
   431             SoulbindId = soulbindId,
 | 
| 
yellowfive@185
 | 
   432             SoulbindNodes = soulbindNodes
 | 
| 
yellowfive@185
 | 
   433             --Essences = essences
 | 
| 
yellowfive@139
 | 
   434         }
 | 
| 
yellowfive@139
 | 
   435 
 | 
| 
yellowfive@139
 | 
   436         if not result.IsBib then
 | 
| 
yellowfive@139
 | 
   437             -- replace if this setup already exists
 | 
| 
yellowfive@139
 | 
   438             local key = -1
 | 
| 
yellowfive@139
 | 
   439             for i,setup in ipairs(Amr.db.char.GearSetups) do
 | 
| 
yellowfive@139
 | 
   440                 if setup.Id == result.Id then
 | 
| 
yellowfive@139
 | 
   441                     key = i
 | 
| 
yellowfive@139
 | 
   442                     break
 | 
| 
yellowfive@139
 | 
   443                 end
 | 
| 
yellowfive@139
 | 
   444             end
 | 
| 
yellowfive@139
 | 
   445 
 | 
| 
yellowfive@139
 | 
   446             if key ~= -1 then
 | 
| 
yellowfive@139
 | 
   447                 Amr.db.char.GearSetups[key] = result
 | 
| 
yellowfive@139
 | 
   448             else
 | 
| 
yellowfive@139
 | 
   449                 table.insert(Amr.db.char.GearSetups, result)
 | 
| 
yellowfive@139
 | 
   450             end
 | 
| 
yellowfive@139
 | 
   451             
 | 
| 
yellowfive@139
 | 
   452             if not isChild then
 | 
| 
yellowfive@139
 | 
   453                 -- if doing a single import of a setup, make it active
 | 
| 
yellowfive@139
 | 
   454                 Amr:SetActiveSetupId(setupId)
 | 
| 
yellowfive@139
 | 
   455             end
 | 
| 
yellowfive@139
 | 
   456         else
 | 
| 
yellowfive@139
 | 
   457             table.insert(Amr.db.char.GearSetups, result)
 | 
| 
yellowfive@139
 | 
   458         end
 | 
| 
yellowfive@124
 | 
   459 
 | 
| 
yellowfive@124
 | 
   460         for k,v in pairs(enchantInfo) do
 | 
| 
yellowfive@124
 | 
   461             Amr.db.char.ExtraEnchantData[k] = v    
 | 
| 
yellowfive@124
 | 
   462         end
 | 
| 
yellowfive@57
 | 
   463 		
 | 
| 
yellowfive@57
 | 
   464 		-- also update shopping list after import
 | 
| 
yellowfive@57
 | 
   465 		Amr:UpdateShoppingData(currentPlayerData)
 | 
| 
yellowfive@57
 | 
   466     end
 | 
| 
yellowfive@57
 | 
   467 end
 | 
| 
yellowfive@161
 | 
   468 
 | 
| 
yellowfive@161
 | 
   469 --
 | 
| 
yellowfive@161
 | 
   470 -- Import a list of items that are junk.
 | 
| 
yellowfive@161
 | 
   471 --
 | 
| 
yellowfive@161
 | 
   472 function Amr:ImportJunkList(data, currentPlayerData)
 | 
| 
yellowfive@161
 | 
   473 
 | 
| 
yellowfive@161
 | 
   474     local data1 = { strsplit("$", data) }
 | 
| 
yellowfive@161
 | 
   475     if #data1 ~= 3 then
 | 
| 
yellowfive@161
 | 
   476         return L.ImportErrorFormat
 | 
| 
yellowfive@161
 | 
   477     end
 | 
| 
yellowfive@161
 | 
   478     
 | 
| 
yellowfive@161
 | 
   479     local parts = { strsplit(";", data1[2]) }
 | 
| 
yellowfive@161
 | 
   480     
 | 
| 
yellowfive@161
 | 
   481     -- require a minimum version
 | 
| 
yellowfive@161
 | 
   482     local ver = tonumber(parts[1])
 | 
| 
yellowfive@161
 | 
   483     if ver < Amr.MIN_IMPORT_VERSION then
 | 
| 
yellowfive@161
 | 
   484         return L.ImportErrorVersion
 | 
| 
yellowfive@161
 | 
   485     end
 | 
| 
yellowfive@161
 | 
   486 
 | 
| 
yellowfive@161
 | 
   487     -- require name match
 | 
| 
yellowfive@161
 | 
   488     local region = parts[2]
 | 
| 
yellowfive@161
 | 
   489     local realm = parts[3]
 | 
| 
yellowfive@161
 | 
   490     local name = parts[4]
 | 
| 
yellowfive@161
 | 
   491     if name ~= currentPlayerData.Name then
 | 
| 
yellowfive@161
 | 
   492         local importPlayerName = name .. " (" .. realm .. ")"
 | 
| 
yellowfive@161
 | 
   493         local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
 | 
| 
yellowfive@161
 | 
   494         return L.ImportErrorChar(importPlayerName, you)
 | 
| 
yellowfive@161
 | 
   495     end
 | 
| 
yellowfive@161
 | 
   496 
 | 
| 
yellowfive@161
 | 
   497     local keepStartPos = 0
 | 
| 
yellowfive@161
 | 
   498     local junkStartPos = 0
 | 
| 
yellowfive@161
 | 
   499     for i = 5, #parts do
 | 
| 
yellowfive@161
 | 
   500         local partString = parts[i]
 | 
| 
yellowfive@161
 | 
   501         if partString == ".k" then
 | 
| 
yellowfive@161
 | 
   502             keepStartPos = i + 1
 | 
| 
yellowfive@161
 | 
   503         elseif partString == ".d" then
 | 
| 
yellowfive@161
 | 
   504             junkStartPos = i + 1
 | 
| 
yellowfive@161
 | 
   505         end
 | 
| 
yellowfive@161
 | 
   506     end
 | 
| 
yellowfive@161
 | 
   507 
 | 
| 
yellowfive@161
 | 
   508     Amr.db.char.JunkData = {}
 | 
| 
yellowfive@161
 | 
   509 
 | 
| 
yellowfive@161
 | 
   510     -- Keep is a lookup by unique id
 | 
| 
yellowfive@161
 | 
   511     local keep = parseItemList(parts, keepStartPos, ".d", false)
 | 
| 
yellowfive@161
 | 
   512     Amr.db.char.JunkData.Keep = {}
 | 
| 
yellowfive@161
 | 
   513     for i = 1, #keep do
 | 
| 
yellowfive@161
 | 
   514         local uniqueId = Amr.GetItemUniqueId(keep[i])
 | 
| 
yellowfive@161
 | 
   515         Amr.db.char.JunkData.Keep[uniqueId] = keep[i]
 | 
| 
yellowfive@161
 | 
   516     end
 | 
| 
yellowfive@161
 | 
   517 
 | 
| 
yellowfive@161
 | 
   518     -- Junk is a simple list of items to discard, in the desired display order
 | 
| 
yellowfive@161
 | 
   519     Amr.db.char.JunkData.Junk = parseItemList(parts, junkStartPos, "n/a", false)
 | 
| 
yellowfive@163
 | 
   520 
 | 
| 
yellowfive@161
 | 
   521     -- extra information contains extra enchant info  
 | 
| 
yellowfive@161
 | 
   522     if #data1 >= 3 then      
 | 
| 
yellowfive@161
 | 
   523         parts = { strsplit("@", data1[3]) }
 | 
| 
yellowfive@161
 | 
   524 
 | 
| 
yellowfive@161
 | 
   525         local enchantInfo = {}
 | 
| 
yellowfive@161
 | 
   526 
 | 
| 
yellowfive@161
 | 
   527         for i = 2, #parts do
 | 
| 
yellowfive@161
 | 
   528             local infoParts = { strsplit("\\", parts[i]) }
 | 
| 
yellowfive@161
 | 
   529             
 | 
| 
yellowfive@161
 | 
   530             if infoParts[1] == "e" then
 | 
| 
yellowfive@161
 | 
   531             
 | 
| 
yellowfive@161
 | 
   532                 local enchObj = {}
 | 
| 
yellowfive@161
 | 
   533                 enchObj.id = tonumber(infoParts[2])
 | 
| 
yellowfive@161
 | 
   534                 enchObj.itemId = tonumber(infoParts[3])
 | 
| 
yellowfive@161
 | 
   535                 enchObj.spellId = tonumber(infoParts[4])
 | 
| 
yellowfive@161
 | 
   536                 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end)
 | 
| 
yellowfive@161
 | 
   537                 
 | 
| 
yellowfive@161
 | 
   538                 local mats = infoParts[6]
 | 
| 
yellowfive@161
 | 
   539                 if string.len(mats) > 0 then
 | 
| 
yellowfive@161
 | 
   540                     enchObj.materials = {}
 | 
| 
yellowfive@161
 | 
   541                     mats = { strsplit(",", mats) }
 | 
| 
yellowfive@161
 | 
   542                     for j = 1, #mats do
 | 
| 
yellowfive@161
 | 
   543                         local kv = { strsplit("=", mats[j]) }
 | 
| 
yellowfive@161
 | 
   544                         enchObj.materials[tonumber(kv[1])] = tonumber(kv[2])
 | 
| 
yellowfive@161
 | 
   545                     end
 | 
| 
yellowfive@161
 | 
   546                 end
 | 
| 
yellowfive@161
 | 
   547                 
 | 
| 
yellowfive@161
 | 
   548                 enchantInfo[enchObj.id] = enchObj            
 | 
| 
yellowfive@161
 | 
   549             end
 | 
| 
yellowfive@161
 | 
   550         end
 | 
| 
yellowfive@161
 | 
   551 
 | 
| 
yellowfive@161
 | 
   552         for k,v in pairs(enchantInfo) do
 | 
| 
yellowfive@161
 | 
   553             Amr.db.char.ExtraEnchantData[k] = v    
 | 
| 
yellowfive@161
 | 
   554         end
 | 
| 
yellowfive@161
 | 
   555     end
 | 
| 
yellowfive@161
 | 
   556 
 | 
| 
yellowfive@161
 | 
   557     -- show the junk window after a successful junk import
 | 
| 
yellowfive@161
 | 
   558     Amr:ShowJunkWindow()
 | 
| 
yellowfive@161
 | 
   559 end |