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