diff Import.lua @ 57:01b63b8ed811 v21

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