annotate Import.lua @ 115:8bef8f88361c

Added tag v53 for changeset 4cd98aa90d78
author yellowfive
date Wed, 04 Oct 2017 01:09:12 -0700
parents 6bbe64d587b4
children e31b02b24488
rev   line source
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@57 17 Amr:RefreshGearTab()
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@69 30
yellowfive@69 31 -- do an import if the data starts and ends with a dollar sign
yellowfive@69 32 local txt = _txtImport:GetText()
yellowfive@69 33 local txtLen = string.len(txt)
yellowfive@69 34 if txtLen > 2 and string.sub(txt, 1, 1) == '$' 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@57 45 lbl:SetWidth(600)
yellowfive@57 46 lbl:SetText(L.ImportHeader)
yellowfive@57 47 lbl:SetPoint("TOP", panelImport.content, "TOP", 0, -10)
yellowfive@57 48 panelImport:AddChild(lbl)
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:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -10)
yellowfive@57 54 _txtImport:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text))
yellowfive@69 55 _txtImport:SetCallback("OnEnterPressed", onTextEnterPressed)
yellowfive@57 56 panelImport:AddChild(_txtImport)
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:SetPoint("TOPLEFT", _txtImport.frame, "BOTTOMLEFT", 0, -10)
yellowfive@57 65 btnImportOk:SetCallback("OnClick", onImportOkClick)
yellowfive@57 66 panelImport:AddChild(btnImportOk)
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:SetPoint("LEFT", btnImportOk.frame, "RIGHT", 20, 0)
yellowfive@57 75 btnImportCancel:SetCallback("OnClick", onImportCancelClick)
yellowfive@57 76 panelImport:AddChild(btnImportCancel)
yellowfive@57 77
yellowfive@57 78 _lblError = AceGUI:Create("AmrUiLabel")
yellowfive@57 79 _lblError:SetWidth(600)
yellowfive@57 80 _lblError:SetFont(Amr.CreateFont("Bold", 14, Amr.Colors.Red))
yellowfive@57 81 _lblError:SetText("")
yellowfive@57 82 _lblError:SetPoint("TOPLEFT", btnImportOk.frame, "BOTTOMLEFT", 0, -20)
yellowfive@57 83 panelImport:AddChild(_lblError)
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@69 91 _panelCover:SetPoint("TOPLEFT", panelImport.frame, "TOPLEFT")
yellowfive@69 92 _panelCover:SetPoint("BOTTOMRIGHT", panelImport.frame, "BOTTOMRIGHT")
yellowfive@69 93 panelImport:AddChild(_panelCover)
yellowfive@69 94
yellowfive@69 95 local coverMsg = AceGUI:Create("AmrUiLabel")
yellowfive@69 96 coverMsg:SetWidth(500)
yellowfive@69 97 coverMsg:SetFont(Amr.CreateFont("Regular", 16, Amr.Colors.TextTan))
yellowfive@69 98 coverMsg:SetJustifyH("MIDDLE")
yellowfive@69 99 coverMsg:SetJustifyV("MIDDLE")
yellowfive@69 100 coverMsg:SetText(L.ImportOverwolfWait)
yellowfive@69 101 coverMsg:SetPoint("CENTER", _panelCover.frame, "CENTER", 0, 20)
yellowfive@69 102 _panelCover:AddChild(coverMsg)
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@57 125 -- Import a character, returning nil on success, otherwise an error message, import result stored in the db.
yellowfive@57 126 --
yellowfive@57 127 function Amr:ImportCharacter(data, isTest)
yellowfive@57 128
yellowfive@57 129 -- make sure all data is up to date before importing and get a local copy of player's current state
yellowfive@57 130 local currentPlayerData = self:ExportCharacter()
yellowfive@57 131
yellowfive@57 132 if data == nil or string.len(data) == 0 then
yellowfive@57 133 return L.ImportErrorEmpty
yellowfive@57 134 end
yellowfive@57 135
yellowfive@57 136 -- if multiple specs are included in the data, parse each individually, then quit
yellowfive@57 137 local specParts = { strsplit("\n", data) }
yellowfive@57 138 if #specParts > 1 then
yellowfive@57 139 for i = 1, #specParts do
yellowfive@57 140 local err = self:ImportCharacter(specParts[i], isTest)
yellowfive@57 141 if err ~= nil then
yellowfive@57 142 return err
yellowfive@57 143 end
yellowfive@57 144 end
yellowfive@57 145 return
yellowfive@57 146 end
yellowfive@57 147
yellowfive@57 148 local data1 = { strsplit("$", data) }
yellowfive@57 149 if #data1 ~= 3 then
yellowfive@57 150 return L.ImportErrorFormat
yellowfive@57 151 end
yellowfive@57 152
yellowfive@57 153 local parts = { strsplit(";", data1[2]) }
yellowfive@57 154
yellowfive@57 155 -- require a minimum version
yellowfive@57 156 local ver = tonumber(parts[1])
yellowfive@57 157 if ver < Amr.MIN_IMPORT_VERSION then
yellowfive@57 158 return L.ImportErrorVersion
yellowfive@57 159 end
yellowfive@57 160
yellowfive@57 161 -- require name match (don't match realm due to language issues for now)
yellowfive@57 162 if not isTest then
yellowfive@57 163 local region = parts[2]
yellowfive@57 164 local realm = parts[3]
yellowfive@57 165 local name = parts[4]
yellowfive@57 166 if name ~= currentPlayerData.Name then
yellowfive@57 167 local importPlayerName = name .. " (" .. realm .. ")"
yellowfive@57 168 local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")"
yellowfive@57 169 return L.ImportErrorChar(importPlayerName, you)
yellowfive@57 170 end
yellowfive@57 171
yellowfive@57 172 -- require race match
yellowfive@57 173 local race = tonumber(parts[6])
yellowfive@57 174 if race ~= Amr.RaceIds[currentPlayerData.Race] then
yellowfive@57 175 return L.ImportErrorRace
yellowfive@57 176 end
yellowfive@57 177
yellowfive@57 178 -- require faction match
yellowfive@57 179 local faction = tonumber(parts[7])
yellowfive@57 180 if faction ~= Amr.FactionIds[currentPlayerData.Faction] then
yellowfive@57 181 return L.ImportErrorFaction
yellowfive@57 182 end
yellowfive@57 183
yellowfive@57 184 -- require level match
yellowfive@57 185 local level = tonumber(parts[8])
yellowfive@57 186 if level ~= currentPlayerData.Level then
yellowfive@57 187 return L.ImportErrorLevel
yellowfive@57 188 end
yellowfive@57 189 end
yellowfive@57 190
yellowfive@57 191 -- if we make it this far, the data is valid, so read item information
yellowfive@57 192 local specSlot = tonumber(parts[10])
yellowfive@57 193
yellowfive@57 194 local importData = {}
yellowfive@57 195
yellowfive@57 196 local itemInfo = {}
yellowfive@57 197 local gemInfo = {}
yellowfive@57 198 local enchantInfo = {}
yellowfive@57 199
yellowfive@57 200 local prevItemId = 0
yellowfive@57 201 local prevGemId = 0
yellowfive@57 202 local prevEnchantId = 0
yellowfive@57 203 local prevUpgradeId = 0
yellowfive@57 204 local prevBonusId = 0
yellowfive@81 205 local prevLevel = 0
yellowfive@57 206 local digits = {
yellowfive@57 207 ["-"] = true,
yellowfive@57 208 ["0"] = true,
yellowfive@57 209 ["1"] = true,
yellowfive@57 210 ["2"] = true,
yellowfive@57 211 ["3"] = true,
yellowfive@57 212 ["4"] = true,
yellowfive@57 213 ["5"] = true,
yellowfive@57 214 ["6"] = true,
yellowfive@57 215 ["7"] = true,
yellowfive@57 216 ["8"] = true,
yellowfive@57 217 ["9"] = true,
yellowfive@57 218 }
yellowfive@81 219 for i = 18, #parts do
yellowfive@57 220 local itemString = parts[i]
yellowfive@57 221 if itemString ~= "" and itemString ~= "_" then
yellowfive@57 222 local tokens = {}
yellowfive@57 223 local bonusIds = {}
yellowfive@89 224 local relicBonusIds = {}
yellowfive@89 225 table.insert(relicBonusIds, {})
yellowfive@89 226 table.insert(relicBonusIds, {})
yellowfive@89 227 table.insert(relicBonusIds, {})
yellowfive@89 228 local hasRelics = false
yellowfive@57 229 local hasBonuses = false
yellowfive@57 230 local token = ""
yellowfive@57 231 local prop = "i"
yellowfive@57 232 local tokenComplete = false
yellowfive@57 233 for j = 1, string.len(itemString) do
yellowfive@57 234 local c = string.sub(itemString, j, j)
yellowfive@57 235 if digits[c] == nil then
yellowfive@57 236 tokenComplete = true
yellowfive@57 237 else
yellowfive@57 238 token = token .. c
yellowfive@57 239 end
yellowfive@57 240
yellowfive@57 241 if tokenComplete or j == string.len(itemString) then
yellowfive@57 242 local val = tonumber(token)
yellowfive@57 243 if prop == "i" then
yellowfive@57 244 val = val + prevItemId
yellowfive@57 245 prevItemId = val
yellowfive@57 246 elseif prop == "u" then
yellowfive@57 247 val = val + prevUpgradeId
yellowfive@57 248 prevUpgradeId = val
yellowfive@81 249 elseif prop == "v" then
yellowfive@81 250 val = val + prevLevel
yellowfive@81 251 prevLevel = val
yellowfive@57 252 elseif prop == "b" then
yellowfive@57 253 val = val + prevBonusId
yellowfive@57 254 prevBonusId = val
yellowfive@57 255 elseif prop == "x" or prop == "y" or prop == "z" then
yellowfive@57 256 val = val + prevGemId
yellowfive@57 257 prevGemId = val
yellowfive@57 258 elseif prop == "e" then
yellowfive@57 259 val = val + prevEnchantId
yellowfive@57 260 prevEnchantId = val
yellowfive@57 261 end
yellowfive@57 262
yellowfive@57 263 if prop == "b" then
yellowfive@57 264 table.insert(bonusIds, val)
yellowfive@57 265 hasBonuses = true
yellowfive@89 266 elseif prop == "m" then
yellowfive@89 267 table.insert(relicBonusIds[1], val)
yellowfive@89 268 hasRelics = true
yellowfive@89 269 elseif prop == "n" then
yellowfive@89 270 table.insert(relicBonusIds[2], val)
yellowfive@89 271 hasRelics = true
yellowfive@89 272 elseif prop == "o" then
yellowfive@89 273 table.insert(relicBonusIds[3], val)
yellowfive@89 274 hasRelics = true
yellowfive@57 275 else
yellowfive@57 276 tokens[prop] = val
yellowfive@57 277 end
yellowfive@57 278
yellowfive@57 279 token = ""
yellowfive@57 280 tokenComplete = false
yellowfive@57 281
yellowfive@57 282 -- we have moved on to the next token
yellowfive@57 283 prop = c
yellowfive@57 284 end
yellowfive@57 285 end
yellowfive@57 286
yellowfive@57 287 local obj = {}
yellowfive@57 288 importData[tonumber(tokens["s"])] = obj
yellowfive@57 289
yellowfive@57 290 obj.id = tokens["i"]
yellowfive@57 291 obj.suffixId = tokens["f"] or 0
yellowfive@57 292 obj.upgradeId = tokens["u"] or 0
yellowfive@81 293 obj.level = tokens["v"] or 0
yellowfive@57 294 obj.enchantId = tokens["e"] or 0
yellowfive@89 295 obj.inventoryId = tokens["t"] or 0
yellowfive@57 296
yellowfive@57 297 obj.gemIds = {}
yellowfive@57 298 table.insert(obj.gemIds, tokens["x"] or 0)
yellowfive@57 299 table.insert(obj.gemIds, tokens["y"] or 0)
yellowfive@57 300 table.insert(obj.gemIds, tokens["z"] or 0)
yellowfive@57 301 table.insert(obj.gemIds, 0)
yellowfive@89 302
yellowfive@89 303 if hasRelics then
yellowfive@89 304 obj.relicBonusIds = relicBonusIds
yellowfive@89 305 end
yellowfive@57 306
yellowfive@57 307 if hasBonuses then
yellowfive@57 308 obj.bonusIds = bonusIds
yellowfive@57 309 end
yellowfive@57 310
yellowfive@57 311 local itemObj = {}
yellowfive@57 312 itemObj.id = obj.id
yellowfive@57 313 itemInfo[obj.id] = itemObj
yellowfive@57 314
yellowfive@57 315 -- look for any socket color information, add to our extra data
yellowfive@57 316 if tokens["c"] then
yellowfive@57 317 itemObj.socketColors = {}
yellowfive@57 318 for j = 1, string.len(tokens["c"]) do
yellowfive@57 319 table.insert(itemObj.socketColors, tonumber(string.sub(tokens["c"], j, j)))
yellowfive@57 320 end
yellowfive@57 321 end
yellowfive@57 322
yellowfive@57 323 -- look for item ID duplicate info, deals with old SoO items
yellowfive@57 324 if tokens["d"] then
yellowfive@57 325 itemObj.duplicateId = tonumber(tokens["d"])
yellowfive@57 326 itemInfo[itemObj.duplicateId] = itemObj
yellowfive@57 327 end
yellowfive@57 328
yellowfive@57 329 end
yellowfive@57 330 end
yellowfive@57 331
yellowfive@57 332 -- now read any extra display information
yellowfive@57 333 parts = { strsplit("@", data1[3]) }
yellowfive@57 334 for i = 1, #parts do
yellowfive@57 335 local infoParts = { strsplit("\\", parts[i]) }
yellowfive@57 336
yellowfive@57 337 if infoParts[1] == "g" then
yellowfive@57 338
yellowfive@57 339 local gemObj = {}
yellowfive@57 340 gemObj.enchantId = tonumber(infoParts[2])
yellowfive@57 341 gemObj.id = tonumber(infoParts[3])
yellowfive@57 342
yellowfive@57 343 local identicalGems = infoParts[4]
yellowfive@57 344 if string.len(identicalGems) > 0 then
yellowfive@57 345 gemObj.identicalGroup = {}
yellowfive@57 346 identicalGems = { strsplit(",", identicalGems) }
yellowfive@57 347 for j = 1, #identicalGems do
yellowfive@57 348 gemObj.identicalGroup[tonumber(identicalGems[j])] = true
yellowfive@57 349 end
yellowfive@57 350 end
yellowfive@57 351
yellowfive@57 352 gemObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end)
yellowfive@57 353 if infoParts[6] == nil or string.len(infoParts[6]) == 0 then
yellowfive@57 354 gemObj.identicalItemGroup = {[gemObj.id]=true}
yellowfive@57 355 else
yellowfive@57 356 local identicalIds = { strsplit(',', infoParts[6]) }
yellowfive@57 357 gemObj.identicalItemGroup = {}
yellowfive@57 358 for j = 1, #identicalIds do
yellowfive@57 359 gemObj.identicalItemGroup[tonumber(identicalIds[j])] = true
yellowfive@57 360 end
yellowfive@57 361 end
yellowfive@57 362
yellowfive@81 363 gemInfo[gemObj.id] = gemObj
yellowfive@57 364
yellowfive@57 365 elseif infoParts[1] == "e" then
yellowfive@57 366
yellowfive@57 367 local enchObj = {}
yellowfive@57 368 enchObj.id = tonumber(infoParts[2])
yellowfive@57 369 enchObj.itemId = tonumber(infoParts[3])
yellowfive@57 370 enchObj.spellId = tonumber(infoParts[4])
yellowfive@57 371 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end)
yellowfive@57 372
yellowfive@57 373 local mats = infoParts[6]
yellowfive@57 374 if string.len(mats) > 0 then
yellowfive@57 375 enchObj.materials = {}
yellowfive@57 376 mats = { strsplit(",", mats) }
yellowfive@57 377 for j = 1, #mats do
yellowfive@57 378 local kv = { strsplit("=", mats[j]) }
yellowfive@57 379 enchObj.materials[tonumber(kv[1])] = tonumber(kv[2])
yellowfive@57 380 end
yellowfive@57 381 end
yellowfive@57 382
yellowfive@57 383 enchantInfo[enchObj.id] = enchObj
yellowfive@57 384
yellowfive@57 385 end
yellowfive@57 386 end
yellowfive@57 387
yellowfive@57 388 if isTest then
yellowfive@57 389 print("spec " .. specSlot)
yellowfive@57 390 -- print result for debugging
yellowfive@57 391 for k,v in pairs(importData) do
yellowfive@57 392 local blah = Amr.CreateItemLink(v)
yellowfive@57 393 --print(blah)
yellowfive@57 394 local name, link = GetItemInfo(blah)
yellowfive@57 395 print(link)
yellowfive@57 396 if link == nil then
yellowfive@57 397 print(blah)
yellowfive@57 398 print("bad item: " .. v.id)
yellowfive@57 399 end
yellowfive@57 400 end
yellowfive@57 401
yellowfive@57 402
yellowfive@57 403 else
yellowfive@57 404 -- we have succeeded, record the result
yellowfive@57 405 Amr.db.char.GearSets[specSlot] = importData
yellowfive@57 406 Amr.db.char.ExtraItemData[specSlot] = itemInfo
yellowfive@57 407 Amr.db.char.ExtraGemData[specSlot] = gemInfo
yellowfive@57 408 Amr.db.char.ExtraEnchantData[specSlot] = enchantInfo
yellowfive@57 409
yellowfive@57 410 -- also update shopping list after import
yellowfive@57 411 Amr:UpdateShoppingData(currentPlayerData)
yellowfive@57 412 end
yellowfive@57 413 end