yellowfive@57: local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") yellowfive@57: local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) yellowfive@57: local AceGUI = LibStub("AceGUI-3.0") yellowfive@57: yellowfive@57: local _txtImport yellowfive@57: local _lblError yellowfive@57: yellowfive@57: local function onImportOkClick(widget) yellowfive@57: local txt = _txtImport:GetText() yellowfive@57: local msg = Amr:ImportCharacter(txt) yellowfive@57: if msg then yellowfive@57: _lblError:SetText(msg) yellowfive@57: _txtImport:SetFocus(true) yellowfive@57: else yellowfive@57: Amr:HideCover() yellowfive@57: Amr:RefreshGearTab() yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: local function onImportCancelClick(widget) yellowfive@57: Amr:HideCover() yellowfive@57: end yellowfive@57: yellowfive@57: local function renderImportWindow(container) yellowfive@57: yellowfive@57: local panelImport = Amr:RenderCoverChrome(container, 700, 450) yellowfive@57: yellowfive@57: local lbl = AceGUI:Create("AmrUiLabel") yellowfive@57: lbl:SetWidth(600) yellowfive@57: lbl:SetText(L.ImportHeader) yellowfive@57: lbl:SetPoint("TOP", panelImport.content, "TOP", 0, -10) yellowfive@57: panelImport:AddChild(lbl) yellowfive@57: yellowfive@57: _txtImport = AceGUI:Create("AmrUiTextarea") yellowfive@57: _txtImport:SetWidth(600) yellowfive@57: _txtImport:SetHeight(300) yellowfive@57: _txtImport:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -10) yellowfive@57: _txtImport:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text)) yellowfive@57: panelImport:AddChild(_txtImport) yellowfive@57: yellowfive@57: local btnImportOk = AceGUI:Create("AmrUiButton") yellowfive@57: btnImportOk:SetText(L.ImportButtonOk) yellowfive@57: btnImportOk:SetBackgroundColor(Amr.Colors.Green) yellowfive@57: btnImportOk:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) yellowfive@57: btnImportOk:SetWidth(120) yellowfive@57: btnImportOk:SetHeight(28) yellowfive@57: btnImportOk:SetPoint("TOPLEFT", _txtImport.frame, "BOTTOMLEFT", 0, -10) yellowfive@57: btnImportOk:SetCallback("OnClick", onImportOkClick) yellowfive@57: panelImport:AddChild(btnImportOk) yellowfive@57: yellowfive@57: local btnImportCancel = AceGUI:Create("AmrUiButton") yellowfive@57: btnImportCancel:SetText(L.ImportButtonCancel) yellowfive@57: btnImportCancel:SetBackgroundColor(Amr.Colors.Green) yellowfive@57: btnImportCancel:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) yellowfive@57: btnImportCancel:SetWidth(120) yellowfive@57: btnImportCancel:SetHeight(28) yellowfive@57: btnImportCancel:SetPoint("LEFT", btnImportOk.frame, "RIGHT", 20, 0) yellowfive@57: btnImportCancel:SetCallback("OnClick", onImportCancelClick) yellowfive@57: panelImport:AddChild(btnImportCancel) yellowfive@57: yellowfive@57: _lblError = AceGUI:Create("AmrUiLabel") yellowfive@57: _lblError:SetWidth(600) yellowfive@57: _lblError:SetFont(Amr.CreateFont("Bold", 14, Amr.Colors.Red)) yellowfive@57: _lblError:SetText("") yellowfive@57: _lblError:SetPoint("TOPLEFT", btnImportOk.frame, "BOTTOMLEFT", 0, -20) yellowfive@57: panelImport:AddChild(_lblError) yellowfive@57: yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:ShowImportWindow() yellowfive@57: -- this is shown as a modal dialog yellowfive@57: Amr:ShowCover(renderImportWindow) yellowfive@57: yellowfive@57: _txtImport:SetText("") yellowfive@57: _txtImport:SetFocus(true) yellowfive@57: end yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------- yellowfive@57: -- Import Parsing yellowfive@57: ---------------------------------------------------------------------------- yellowfive@57: yellowfive@57: -- yellowfive@57: -- Import a character, returning nil on success, otherwise an error message, import result stored in the db. yellowfive@57: -- yellowfive@57: function Amr:ImportCharacter(data, isTest) yellowfive@57: yellowfive@57: -- make sure all data is up to date before importing and get a local copy of player's current state yellowfive@57: local currentPlayerData = self:ExportCharacter() yellowfive@57: yellowfive@57: if data == nil or string.len(data) == 0 then yellowfive@57: return L.ImportErrorEmpty yellowfive@57: end yellowfive@57: yellowfive@57: -- if multiple specs are included in the data, parse each individually, then quit yellowfive@57: local specParts = { strsplit("\n", data) } yellowfive@57: if #specParts > 1 then yellowfive@57: for i = 1, #specParts do yellowfive@57: local err = self:ImportCharacter(specParts[i], isTest) yellowfive@57: if err ~= nil then yellowfive@57: return err yellowfive@57: end yellowfive@57: end yellowfive@57: return yellowfive@57: end yellowfive@57: yellowfive@57: local data1 = { strsplit("$", data) } yellowfive@57: if #data1 ~= 3 then yellowfive@57: return L.ImportErrorFormat yellowfive@57: end yellowfive@57: yellowfive@57: local parts = { strsplit(";", data1[2]) } yellowfive@57: yellowfive@57: -- require a minimum version yellowfive@57: local ver = tonumber(parts[1]) yellowfive@57: if ver < Amr.MIN_IMPORT_VERSION then yellowfive@57: return L.ImportErrorVersion yellowfive@57: end yellowfive@57: yellowfive@57: -- require name match (don't match realm due to language issues for now) yellowfive@57: if not isTest then yellowfive@57: local region = parts[2] yellowfive@57: local realm = parts[3] yellowfive@57: local name = parts[4] yellowfive@57: if name ~= currentPlayerData.Name then yellowfive@57: local importPlayerName = name .. " (" .. realm .. ")" yellowfive@57: local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")" yellowfive@57: return L.ImportErrorChar(importPlayerName, you) yellowfive@57: end yellowfive@57: yellowfive@57: -- require race match yellowfive@57: local race = tonumber(parts[6]) yellowfive@57: if race ~= Amr.RaceIds[currentPlayerData.Race] then yellowfive@57: return L.ImportErrorRace yellowfive@57: end yellowfive@57: yellowfive@57: -- require faction match yellowfive@57: local faction = tonumber(parts[7]) yellowfive@57: if faction ~= Amr.FactionIds[currentPlayerData.Faction] then yellowfive@57: return L.ImportErrorFaction yellowfive@57: end yellowfive@57: yellowfive@57: -- require level match yellowfive@57: local level = tonumber(parts[8]) yellowfive@57: if level ~= currentPlayerData.Level then yellowfive@57: return L.ImportErrorLevel yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- if we make it this far, the data is valid, so read item information yellowfive@57: local specSlot = tonumber(parts[10]) yellowfive@57: yellowfive@57: local importData = {} yellowfive@57: yellowfive@57: local itemInfo = {} yellowfive@57: local gemInfo = {} yellowfive@57: local enchantInfo = {} yellowfive@57: yellowfive@57: local prevItemId = 0 yellowfive@57: local prevGemId = 0 yellowfive@57: local prevEnchantId = 0 yellowfive@57: local prevUpgradeId = 0 yellowfive@57: local prevBonusId = 0 yellowfive@57: local digits = { yellowfive@57: ["-"] = true, yellowfive@57: ["0"] = true, yellowfive@57: ["1"] = true, yellowfive@57: ["2"] = true, yellowfive@57: ["3"] = true, yellowfive@57: ["4"] = true, yellowfive@57: ["5"] = true, yellowfive@57: ["6"] = true, yellowfive@57: ["7"] = true, yellowfive@57: ["8"] = true, yellowfive@57: ["9"] = true, yellowfive@57: } yellowfive@57: for i = 16, #parts do yellowfive@57: local itemString = parts[i] yellowfive@57: if itemString ~= "" and itemString ~= "_" then yellowfive@57: local tokens = {} yellowfive@57: local bonusIds = {} yellowfive@57: local hasBonuses = false yellowfive@57: local token = "" yellowfive@57: local prop = "i" yellowfive@57: local tokenComplete = false yellowfive@57: for j = 1, string.len(itemString) do yellowfive@57: local c = string.sub(itemString, j, j) yellowfive@57: if digits[c] == nil then yellowfive@57: tokenComplete = true yellowfive@57: else yellowfive@57: token = token .. c yellowfive@57: end yellowfive@57: yellowfive@57: if tokenComplete or j == string.len(itemString) then yellowfive@57: local val = tonumber(token) yellowfive@57: if prop == "i" then yellowfive@57: val = val + prevItemId yellowfive@57: prevItemId = val yellowfive@57: elseif prop == "u" then yellowfive@57: val = val + prevUpgradeId yellowfive@57: prevUpgradeId = val yellowfive@57: elseif prop == "b" then yellowfive@57: val = val + prevBonusId yellowfive@57: prevBonusId = val yellowfive@57: elseif prop == "x" or prop == "y" or prop == "z" then yellowfive@57: val = val + prevGemId yellowfive@57: prevGemId = val yellowfive@57: elseif prop == "e" then yellowfive@57: val = val + prevEnchantId yellowfive@57: prevEnchantId = val yellowfive@57: end yellowfive@57: yellowfive@57: if prop == "b" then yellowfive@57: table.insert(bonusIds, val) yellowfive@57: hasBonuses = true yellowfive@57: else yellowfive@57: tokens[prop] = val yellowfive@57: end yellowfive@57: yellowfive@57: token = "" yellowfive@57: tokenComplete = false yellowfive@57: yellowfive@57: -- we have moved on to the next token yellowfive@57: prop = c yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: local obj = {} yellowfive@57: importData[tonumber(tokens["s"])] = obj yellowfive@57: yellowfive@57: obj.id = tokens["i"] yellowfive@57: obj.suffixId = tokens["f"] or 0 yellowfive@57: obj.upgradeId = tokens["u"] or 0 yellowfive@57: obj.enchantId = tokens["e"] or 0 yellowfive@57: yellowfive@57: obj.gemIds = {} yellowfive@57: table.insert(obj.gemIds, tokens["x"] or 0) yellowfive@57: table.insert(obj.gemIds, tokens["y"] or 0) yellowfive@57: table.insert(obj.gemIds, tokens["z"] or 0) yellowfive@57: table.insert(obj.gemIds, 0) yellowfive@57: yellowfive@57: if hasBonuses then yellowfive@57: obj.bonusIds = bonusIds yellowfive@57: end yellowfive@57: yellowfive@57: local itemObj = {} yellowfive@57: itemObj.id = obj.id yellowfive@57: itemInfo[obj.id] = itemObj yellowfive@57: yellowfive@57: -- look for any socket color information, add to our extra data yellowfive@57: if tokens["c"] then yellowfive@57: itemObj.socketColors = {} yellowfive@57: for j = 1, string.len(tokens["c"]) do yellowfive@57: table.insert(itemObj.socketColors, tonumber(string.sub(tokens["c"], j, j))) yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- look for item ID duplicate info, deals with old SoO items yellowfive@57: if tokens["d"] then yellowfive@57: itemObj.duplicateId = tonumber(tokens["d"]) yellowfive@57: itemInfo[itemObj.duplicateId] = itemObj yellowfive@57: end yellowfive@57: yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- now read any extra display information yellowfive@57: parts = { strsplit("@", data1[3]) } yellowfive@57: for i = 1, #parts do yellowfive@57: local infoParts = { strsplit("\\", parts[i]) } yellowfive@57: yellowfive@57: if infoParts[1] == "g" then yellowfive@57: yellowfive@57: local gemObj = {} yellowfive@57: gemObj.enchantId = tonumber(infoParts[2]) yellowfive@57: gemObj.id = tonumber(infoParts[3]) yellowfive@57: yellowfive@57: local identicalGems = infoParts[4] yellowfive@57: if string.len(identicalGems) > 0 then yellowfive@57: gemObj.identicalGroup = {} yellowfive@57: identicalGems = { strsplit(",", identicalGems) } yellowfive@57: for j = 1, #identicalGems do yellowfive@57: gemObj.identicalGroup[tonumber(identicalGems[j])] = true yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: gemObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end) yellowfive@57: if infoParts[6] == nil or string.len(infoParts[6]) == 0 then yellowfive@57: gemObj.identicalItemGroup = {[gemObj.id]=true} yellowfive@57: else yellowfive@57: local identicalIds = { strsplit(',', infoParts[6]) } yellowfive@57: gemObj.identicalItemGroup = {} yellowfive@57: for j = 1, #identicalIds do yellowfive@57: gemObj.identicalItemGroup[tonumber(identicalIds[j])] = true yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: gemInfo[gemObj.enchantId] = gemObj yellowfive@57: yellowfive@57: elseif infoParts[1] == "e" then yellowfive@57: yellowfive@57: local enchObj = {} yellowfive@57: enchObj.id = tonumber(infoParts[2]) yellowfive@57: enchObj.itemId = tonumber(infoParts[3]) yellowfive@57: enchObj.spellId = tonumber(infoParts[4]) yellowfive@57: enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end) yellowfive@57: yellowfive@57: local mats = infoParts[6] yellowfive@57: if string.len(mats) > 0 then yellowfive@57: enchObj.materials = {} yellowfive@57: mats = { strsplit(",", mats) } yellowfive@57: for j = 1, #mats do yellowfive@57: local kv = { strsplit("=", mats[j]) } yellowfive@57: enchObj.materials[tonumber(kv[1])] = tonumber(kv[2]) yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: enchantInfo[enchObj.id] = enchObj yellowfive@57: yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: if isTest then yellowfive@57: print("spec " .. specSlot) yellowfive@57: -- print result for debugging yellowfive@57: for k,v in pairs(importData) do yellowfive@57: local blah = Amr.CreateItemLink(v) yellowfive@57: --print(blah) yellowfive@57: local name, link = GetItemInfo(blah) yellowfive@57: print(link) yellowfive@57: if link == nil then yellowfive@57: print(blah) yellowfive@57: print("bad item: " .. v.id) yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: yellowfive@57: else yellowfive@57: -- we have succeeded, record the result yellowfive@57: Amr.db.char.GearSets[specSlot] = importData yellowfive@57: Amr.db.char.ExtraItemData[specSlot] = itemInfo yellowfive@57: Amr.db.char.ExtraGemData[specSlot] = gemInfo yellowfive@57: Amr.db.char.ExtraEnchantData[specSlot] = enchantInfo yellowfive@57: yellowfive@57: -- also update shopping list after import yellowfive@57: Amr:UpdateShoppingData(currentPlayerData) yellowfive@57: end yellowfive@57: end