Mercurial > wow > askmrrobot
comparison Import.lua @ 57:01b63b8ed811 v21
total rewrite to version 21
| author | yellowfive |
|---|---|
| date | Fri, 05 Jun 2015 11:05:15 -0700 |
| parents | |
| children | 69db1c3025ac |
comparison
equal
deleted
inserted
replaced
| 56:75431c084aa0 | 57:01b63b8ed811 |
|---|---|
| 1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") | |
| 2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) | |
| 3 local AceGUI = LibStub("AceGUI-3.0") | |
| 4 | |
| 5 local _txtImport | |
| 6 local _lblError | |
| 7 | |
| 8 local function onImportOkClick(widget) | |
| 9 local txt = _txtImport:GetText() | |
| 10 local msg = Amr:ImportCharacter(txt) | |
| 11 if msg then | |
| 12 _lblError:SetText(msg) | |
| 13 _txtImport:SetFocus(true) | |
| 14 else | |
| 15 Amr:HideCover() | |
| 16 Amr:RefreshGearTab() | |
| 17 end | |
| 18 end | |
| 19 | |
| 20 local function onImportCancelClick(widget) | |
| 21 Amr:HideCover() | |
| 22 end | |
| 23 | |
| 24 local function renderImportWindow(container) | |
| 25 | |
| 26 local panelImport = Amr:RenderCoverChrome(container, 700, 450) | |
| 27 | |
| 28 local lbl = AceGUI:Create("AmrUiLabel") | |
| 29 lbl:SetWidth(600) | |
| 30 lbl:SetText(L.ImportHeader) | |
| 31 lbl:SetPoint("TOP", panelImport.content, "TOP", 0, -10) | |
| 32 panelImport:AddChild(lbl) | |
| 33 | |
| 34 _txtImport = AceGUI:Create("AmrUiTextarea") | |
| 35 _txtImport:SetWidth(600) | |
| 36 _txtImport:SetHeight(300) | |
| 37 _txtImport:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -10) | |
| 38 _txtImport:SetFont(Amr.CreateFont("Regular", 12, Amr.Colors.Text)) | |
| 39 panelImport:AddChild(_txtImport) | |
| 40 | |
| 41 local btnImportOk = AceGUI:Create("AmrUiButton") | |
| 42 btnImportOk:SetText(L.ImportButtonOk) | |
| 43 btnImportOk:SetBackgroundColor(Amr.Colors.Green) | |
| 44 btnImportOk:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) | |
| 45 btnImportOk:SetWidth(120) | |
| 46 btnImportOk:SetHeight(28) | |
| 47 btnImportOk:SetPoint("TOPLEFT", _txtImport.frame, "BOTTOMLEFT", 0, -10) | |
| 48 btnImportOk:SetCallback("OnClick", onImportOkClick) | |
| 49 panelImport:AddChild(btnImportOk) | |
| 50 | |
| 51 local btnImportCancel = AceGUI:Create("AmrUiButton") | |
| 52 btnImportCancel:SetText(L.ImportButtonCancel) | |
| 53 btnImportCancel:SetBackgroundColor(Amr.Colors.Green) | |
| 54 btnImportCancel:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) | |
| 55 btnImportCancel:SetWidth(120) | |
| 56 btnImportCancel:SetHeight(28) | |
| 57 btnImportCancel:SetPoint("LEFT", btnImportOk.frame, "RIGHT", 20, 0) | |
| 58 btnImportCancel:SetCallback("OnClick", onImportCancelClick) | |
| 59 panelImport:AddChild(btnImportCancel) | |
| 60 | |
| 61 _lblError = AceGUI:Create("AmrUiLabel") | |
| 62 _lblError:SetWidth(600) | |
| 63 _lblError:SetFont(Amr.CreateFont("Bold", 14, Amr.Colors.Red)) | |
| 64 _lblError:SetText("") | |
| 65 _lblError:SetPoint("TOPLEFT", btnImportOk.frame, "BOTTOMLEFT", 0, -20) | |
| 66 panelImport:AddChild(_lblError) | |
| 67 | |
| 68 end | |
| 69 | |
| 70 function Amr:ShowImportWindow() | |
| 71 -- this is shown as a modal dialog | |
| 72 Amr:ShowCover(renderImportWindow) | |
| 73 | |
| 74 _txtImport:SetText("") | |
| 75 _txtImport:SetFocus(true) | |
| 76 end | |
| 77 | |
| 78 ---------------------------------------------------------------------------- | |
| 79 -- Import Parsing | |
| 80 ---------------------------------------------------------------------------- | |
| 81 | |
| 82 -- | |
| 83 -- Import a character, returning nil on success, otherwise an error message, import result stored in the db. | |
| 84 -- | |
| 85 function Amr:ImportCharacter(data, isTest) | |
| 86 | |
| 87 -- make sure all data is up to date before importing and get a local copy of player's current state | |
| 88 local currentPlayerData = self:ExportCharacter() | |
| 89 | |
| 90 if data == nil or string.len(data) == 0 then | |
| 91 return L.ImportErrorEmpty | |
| 92 end | |
| 93 | |
| 94 -- if multiple specs are included in the data, parse each individually, then quit | |
| 95 local specParts = { strsplit("\n", data) } | |
| 96 if #specParts > 1 then | |
| 97 for i = 1, #specParts do | |
| 98 local err = self:ImportCharacter(specParts[i], isTest) | |
| 99 if err ~= nil then | |
| 100 return err | |
| 101 end | |
| 102 end | |
| 103 return | |
| 104 end | |
| 105 | |
| 106 local data1 = { strsplit("$", data) } | |
| 107 if #data1 ~= 3 then | |
| 108 return L.ImportErrorFormat | |
| 109 end | |
| 110 | |
| 111 local parts = { strsplit(";", data1[2]) } | |
| 112 | |
| 113 -- require a minimum version | |
| 114 local ver = tonumber(parts[1]) | |
| 115 if ver < Amr.MIN_IMPORT_VERSION then | |
| 116 return L.ImportErrorVersion | |
| 117 end | |
| 118 | |
| 119 -- require name match (don't match realm due to language issues for now) | |
| 120 if not isTest then | |
| 121 local region = parts[2] | |
| 122 local realm = parts[3] | |
| 123 local name = parts[4] | |
| 124 if name ~= currentPlayerData.Name then | |
| 125 local importPlayerName = name .. " (" .. realm .. ")" | |
| 126 local you = currentPlayerData.Name .. " (" .. currentPlayerData.Realm .. ")" | |
| 127 return L.ImportErrorChar(importPlayerName, you) | |
| 128 end | |
| 129 | |
| 130 -- require race match | |
| 131 local race = tonumber(parts[6]) | |
| 132 if race ~= Amr.RaceIds[currentPlayerData.Race] then | |
| 133 return L.ImportErrorRace | |
| 134 end | |
| 135 | |
| 136 -- require faction match | |
| 137 local faction = tonumber(parts[7]) | |
| 138 if faction ~= Amr.FactionIds[currentPlayerData.Faction] then | |
| 139 return L.ImportErrorFaction | |
| 140 end | |
| 141 | |
| 142 -- require level match | |
| 143 local level = tonumber(parts[8]) | |
| 144 if level ~= currentPlayerData.Level then | |
| 145 return L.ImportErrorLevel | |
| 146 end | |
| 147 end | |
| 148 | |
| 149 -- if we make it this far, the data is valid, so read item information | |
| 150 local specSlot = tonumber(parts[10]) | |
| 151 | |
| 152 local importData = {} | |
| 153 | |
| 154 local itemInfo = {} | |
| 155 local gemInfo = {} | |
| 156 local enchantInfo = {} | |
| 157 | |
| 158 local prevItemId = 0 | |
| 159 local prevGemId = 0 | |
| 160 local prevEnchantId = 0 | |
| 161 local prevUpgradeId = 0 | |
| 162 local prevBonusId = 0 | |
| 163 local digits = { | |
| 164 ["-"] = true, | |
| 165 ["0"] = true, | |
| 166 ["1"] = true, | |
| 167 ["2"] = true, | |
| 168 ["3"] = true, | |
| 169 ["4"] = true, | |
| 170 ["5"] = true, | |
| 171 ["6"] = true, | |
| 172 ["7"] = true, | |
| 173 ["8"] = true, | |
| 174 ["9"] = true, | |
| 175 } | |
| 176 for i = 16, #parts do | |
| 177 local itemString = parts[i] | |
| 178 if itemString ~= "" and itemString ~= "_" then | |
| 179 local tokens = {} | |
| 180 local bonusIds = {} | |
| 181 local hasBonuses = false | |
| 182 local token = "" | |
| 183 local prop = "i" | |
| 184 local tokenComplete = false | |
| 185 for j = 1, string.len(itemString) do | |
| 186 local c = string.sub(itemString, j, j) | |
| 187 if digits[c] == nil then | |
| 188 tokenComplete = true | |
| 189 else | |
| 190 token = token .. c | |
| 191 end | |
| 192 | |
| 193 if tokenComplete or j == string.len(itemString) then | |
| 194 local val = tonumber(token) | |
| 195 if prop == "i" then | |
| 196 val = val + prevItemId | |
| 197 prevItemId = val | |
| 198 elseif prop == "u" then | |
| 199 val = val + prevUpgradeId | |
| 200 prevUpgradeId = val | |
| 201 elseif prop == "b" then | |
| 202 val = val + prevBonusId | |
| 203 prevBonusId = val | |
| 204 elseif prop == "x" or prop == "y" or prop == "z" then | |
| 205 val = val + prevGemId | |
| 206 prevGemId = val | |
| 207 elseif prop == "e" then | |
| 208 val = val + prevEnchantId | |
| 209 prevEnchantId = val | |
| 210 end | |
| 211 | |
| 212 if prop == "b" then | |
| 213 table.insert(bonusIds, val) | |
| 214 hasBonuses = true | |
| 215 else | |
| 216 tokens[prop] = val | |
| 217 end | |
| 218 | |
| 219 token = "" | |
| 220 tokenComplete = false | |
| 221 | |
| 222 -- we have moved on to the next token | |
| 223 prop = c | |
| 224 end | |
| 225 end | |
| 226 | |
| 227 local obj = {} | |
| 228 importData[tonumber(tokens["s"])] = obj | |
| 229 | |
| 230 obj.id = tokens["i"] | |
| 231 obj.suffixId = tokens["f"] or 0 | |
| 232 obj.upgradeId = tokens["u"] or 0 | |
| 233 obj.enchantId = tokens["e"] or 0 | |
| 234 | |
| 235 obj.gemIds = {} | |
| 236 table.insert(obj.gemIds, tokens["x"] or 0) | |
| 237 table.insert(obj.gemIds, tokens["y"] or 0) | |
| 238 table.insert(obj.gemIds, tokens["z"] or 0) | |
| 239 table.insert(obj.gemIds, 0) | |
| 240 | |
| 241 if hasBonuses then | |
| 242 obj.bonusIds = bonusIds | |
| 243 end | |
| 244 | |
| 245 local itemObj = {} | |
| 246 itemObj.id = obj.id | |
| 247 itemInfo[obj.id] = itemObj | |
| 248 | |
| 249 -- look for any socket color information, add to our extra data | |
| 250 if tokens["c"] then | |
| 251 itemObj.socketColors = {} | |
| 252 for j = 1, string.len(tokens["c"]) do | |
| 253 table.insert(itemObj.socketColors, tonumber(string.sub(tokens["c"], j, j))) | |
| 254 end | |
| 255 end | |
| 256 | |
| 257 -- look for item ID duplicate info, deals with old SoO items | |
| 258 if tokens["d"] then | |
| 259 itemObj.duplicateId = tonumber(tokens["d"]) | |
| 260 itemInfo[itemObj.duplicateId] = itemObj | |
| 261 end | |
| 262 | |
| 263 end | |
| 264 end | |
| 265 | |
| 266 -- now read any extra display information | |
| 267 parts = { strsplit("@", data1[3]) } | |
| 268 for i = 1, #parts do | |
| 269 local infoParts = { strsplit("\\", parts[i]) } | |
| 270 | |
| 271 if infoParts[1] == "g" then | |
| 272 | |
| 273 local gemObj = {} | |
| 274 gemObj.enchantId = tonumber(infoParts[2]) | |
| 275 gemObj.id = tonumber(infoParts[3]) | |
| 276 | |
| 277 local identicalGems = infoParts[4] | |
| 278 if string.len(identicalGems) > 0 then | |
| 279 gemObj.identicalGroup = {} | |
| 280 identicalGems = { strsplit(",", identicalGems) } | |
| 281 for j = 1, #identicalGems do | |
| 282 gemObj.identicalGroup[tonumber(identicalGems[j])] = true | |
| 283 end | |
| 284 end | |
| 285 | |
| 286 gemObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end) | |
| 287 if infoParts[6] == nil or string.len(infoParts[6]) == 0 then | |
| 288 gemObj.identicalItemGroup = {[gemObj.id]=true} | |
| 289 else | |
| 290 local identicalIds = { strsplit(',', infoParts[6]) } | |
| 291 gemObj.identicalItemGroup = {} | |
| 292 for j = 1, #identicalIds do | |
| 293 gemObj.identicalItemGroup[tonumber(identicalIds[j])] = true | |
| 294 end | |
| 295 end | |
| 296 | |
| 297 gemInfo[gemObj.enchantId] = gemObj | |
| 298 | |
| 299 elseif infoParts[1] == "e" then | |
| 300 | |
| 301 local enchObj = {} | |
| 302 enchObj.id = tonumber(infoParts[2]) | |
| 303 enchObj.itemId = tonumber(infoParts[3]) | |
| 304 enchObj.spellId = tonumber(infoParts[4]) | |
| 305 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.StatsShort[s] end) | |
| 306 | |
| 307 local mats = infoParts[6] | |
| 308 if string.len(mats) > 0 then | |
| 309 enchObj.materials = {} | |
| 310 mats = { strsplit(",", mats) } | |
| 311 for j = 1, #mats do | |
| 312 local kv = { strsplit("=", mats[j]) } | |
| 313 enchObj.materials[tonumber(kv[1])] = tonumber(kv[2]) | |
| 314 end | |
| 315 end | |
| 316 | |
| 317 enchantInfo[enchObj.id] = enchObj | |
| 318 | |
| 319 end | |
| 320 end | |
| 321 | |
| 322 if isTest then | |
| 323 print("spec " .. specSlot) | |
| 324 -- print result for debugging | |
| 325 for k,v in pairs(importData) do | |
| 326 local blah = Amr.CreateItemLink(v) | |
| 327 --print(blah) | |
| 328 local name, link = GetItemInfo(blah) | |
| 329 print(link) | |
| 330 if link == nil then | |
| 331 print(blah) | |
| 332 print("bad item: " .. v.id) | |
| 333 end | |
| 334 end | |
| 335 | |
| 336 | |
| 337 else | |
| 338 -- we have succeeded, record the result | |
| 339 Amr.db.char.GearSets[specSlot] = importData | |
| 340 Amr.db.char.ExtraItemData[specSlot] = itemInfo | |
| 341 Amr.db.char.ExtraGemData[specSlot] = gemInfo | |
| 342 Amr.db.char.ExtraEnchantData[specSlot] = enchantInfo | |
| 343 | |
| 344 -- also update shopping list after import | |
| 345 Amr:UpdateShoppingData(currentPlayerData) | |
| 346 end | |
| 347 end |
