Files
PathOfBuilding/Classes/ImportTab.lua
Openarl 3f1af656f4 Release 1.0.13
- Added scrollbar to items tab
 - Fixed minor issues with scroll bars
2016-09-01 23:13:38 +10:00

270 lines
13 KiB
Lua

-- Path of Building
--
-- Module: Import Tab
-- Import/Export tab for the current build.
--
local launch, main = ...
local ipairs = ipairs
local t_insert = table.insert
local ImportTabClass = common.NewClass("ImportTab", "ControlHost", "Control", function(self, build)
self.ControlHost()
self.Control()
self.build = build
self.charImportMode = "GETACCOUNTNAME"
self.charImportStatus = "Idle"
self.controls.sectionCharImport = common.New("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, 10, 18, 600, 210, "Character Import")
self.controls.charImportStatusLabel = common.New("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, 6, 14, 200, 16, function()
return "^7Character import status: "..self.charImportStatus
end)
-- Stage: input account name
self.controls.accountNameHeader = common.New("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, 6, 40, 200, 16, "^7To start importing a character, enter the character's account name:")
self.controls.accountNameHeader.shown = function()
return self.charImportMode == "GETACCOUNTNAME"
end
self.controls.accountName = common.New("EditControl", {"TOPLEFT",self.controls.accountNameHeader,"BOTTOMLEFT"}, 0, 4, 200, 20, main.lastAccountName or "", nil, "[%C]", 50)
self.controls.accountNameGo = common.New("ButtonControl", {"LEFT",self.controls.accountName,"RIGHT"}, 8, 0, 60, 20, "Start", function()
self.controls.sessionInput.buf = ""
self:DownloadCharacterList()
end)
self.controls.accountNameGo.enabled = function()
return self.controls.accountName.buf:match("%S")
end
-- Stage: input POESESSID
self.controls.sessionHeader = common.New("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, 6, 40, 200, 14)
self.controls.sessionHeader.label = function()
return [[
^7The list of characters on ']]..self.controls.accountName.buf..[[' couldn't be retrieved. This may be because:
1. The account name is wrong, or
2. The account's privacy settings hide the characters tab (this is the default setting).
If this is your account, you can either:
1. Change your privacy settings to show you characters tab and then retry, or
2. Enter a valid POESESSID below.
You can get this from your web browser's cookies while logged into the Path of Exile website.
]]
end
self.controls.sessionHeader.shown = function()
return self.charImportMode == "GETSESSIONID"
end
self.controls.sessionRetry = common.New("ButtonControl", {"TOPLEFT",self.controls.sessionHeader,"TOPLEFT"}, 0, 108, 60, 20, "Retry", function()
self.controls.sessionInput.buf = ""
self:DownloadCharacterList()
end)
self.controls.sessionCancel = common.New("ButtonControl", {"LEFT",self.controls.sessionRetry,"RIGHT"}, 8, 0, 60, 20, "Cancel", function()
self.charImportMode = "GETACCOUNTNAME"
self.charImportStatus = "Idle"
end)
self.controls.sessionInput = common.New("EditControl", {"TOPLEFT",self.controls.sessionRetry,"BOTTOMLEFT"}, 0, 8, 350, 20, "", "POESESSID", "[%x]", 32)
self.controls.sessionGo = common.New("ButtonControl", {"LEFT",self.controls.sessionInput,"RIGHT"}, 8, 0, 60, 20, "Go", function()
self:DownloadCharacterList()
end)
self.controls.sessionGo.enabled = function()
return #self.controls.sessionInput.buf == 32
end
-- Stage: select character and import data
self.controls.charSelectHeader = common.New("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, 6, 40, 200, 16, "^7Choose character to import data from:")
self.controls.charSelectHeader.shown = function()
return self.charImportMode == "SELECTCHAR" or self.charImportMode == "IMPORTING"
end
self.controls.charSelect = common.New("DropDownControl", {"TOPLEFT",self.controls.charSelectHeader,"BOTTOMLEFT"}, 0, 4, 400, 18)
self.controls.charSelect.enabled = function()
return self.charImportMode == "SELECTCHAR"
end
self.controls.charImportHeader = common.New("LabelControl", {"TOPLEFT",self.controls.charSelect,"BOTTOMLEFT"}, 0, 16, 200, 16, "Import:")
self.controls.charImport = common.New("ButtonControl", {"LEFT",self.controls.charImportHeader, "RIGHT"}, 8, 0, 100, 20, "Passive Tree", function()
if self.build.spec:CountAllocNodes() > 0 then
main:OpenConfirmPopup("Character Import", "Importing the passive tree will overwrite your current tree.", "Import", function()
self:DownloadPassiveTree()
end)
else
self:DownloadPassiveTree()
end
end)
self.controls.charImport.enabled = function()
return self.charImportMode == "SELECTCHAR"
end
self.controls.charDone = common.New("ButtonControl", {"TOPLEFT",self.controls.charImportHeader,"BOTTOMLEFT"}, 0, 30, 60, 20, "Done", function()
self.charImportMode = "GETACCOUNTNAME"
self.charImportStatus = "Idle"
end)
-- Build import/export
self.controls.sectionBuild = common.New("SectionControl", {"TOPLEFT",self.controls.sectionCharImport,"BOTTOMLEFT"}, 0, 18, 600, 200, "Build Sharing")
self.controls.generateCodeLabel = common.New("LabelControl", {"TOPLEFT",self.controls.sectionBuild,"TOPLEFT"}, 6, 14, 0, 16, "^7Generate a code to share this build with other Path of Building users:")
self.controls.generateCode = common.New("ButtonControl", {"LEFT",self.controls.generateCodeLabel,"RIGHT"}, 4, 0, 80, 20, "Generate", function()
self.controls.generateCodeOut:SetText(common.base64.encode(Deflate(self.build:SaveDB("code"))):gsub("+","-"):gsub("/","_"))
end)
self.controls.generateCodeOut = common.New("EditControl", {"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, 0, 8, 250, 20, "", "Code", "[%z]")
self.controls.generateCodeOut.enabled = function()
return #self.controls.generateCodeOut.buf > 0
end
self.controls.generateCodeCopy = common.New("ButtonControl", {"LEFT",self.controls.generateCodeOut,"RIGHT"}, 8, 0, 60, 20, "Copy", function()
Copy(self.controls.generateCodeOut.buf)
self.controls.generateCodeOut:SetText("")
end)
self.controls.generateCodeCopy.enabled = function()
return #self.controls.generateCodeOut.buf > 0
end
self.controls.generateCodeNote = common.New("LabelControl", {"TOPLEFT",self.controls.generateCodeOut,"BOTTOMLEFT"}, 0, 4, 0, 14, "^7Note: this code can be very long; it may be easiest to share it using Pastebin or similar.")
self.controls.importCodeHeader = common.New("LabelControl", {"TOPLEFT",self.controls.generateCodeNote,"BOTTOMLEFT"}, 0, 26, 0, 16, "^7To import a build, enter the code here:")
self.controls.importCodeIn = common.New("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, 0, 4, 250, 20, "", nil, "[%w_%-=]", nil, function(buf)
if #buf == 0 then
self.importCodeState = nil
return
end
self.importCodeState = "INVALID"
local xmlText = Inflate(common.base64.decode(buf:gsub("-","+"):gsub("_","/")))
if not xmlText then
return
end
self.importCodeState = "VALID"
self.importCodeXML = xmlText
end)
self.controls.importCodeState = common.New("LabelControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, 4, 0, 0, 16)
self.controls.importCodeState.label = function()
return (self.importCodeState == "VALID" and data.colorCodes.POSITIVE.."Code is valid") or (self.importCodeState == "INVALID" and data.colorCodes.NEGATIVE.."Invalid code") or ""
end
self.controls.importCodeMode = common.New("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, 0, 4, 160, 20, { "Import to this build", "Import to a new build:" })
self.controls.importCodeMode.enabled = function()
return self.importCodeState == "VALID"
end
self.controls.importCodeBuildName = common.New("EditControl", {"LEFT",self.controls.importCodeMode,"RIGHT"}, 4, 0, 400, 20, "", "New build name", "[%w _+-.()]", 50)
self.controls.importCodeBuildName.enabled = function()
return self.importCodeState == "VALID" and self.controls.importCodeMode.sel == 2
end
self.controls.importCodeGo = common.New("ButtonControl", {"TOPLEFT",self.controls.importCodeMode,"BOTTOMLEFT"}, 0, 8, 60, 20, "Import", function()
if self.controls.importCodeMode.sel == 1 then
main:OpenConfirmPopup("Build Import", "^xFF9922Warning:^7 Importing to the current build will erase ALL existing data for this build.\nThis cannot be undone.", "Import", function()
self:ImportToBuild(self.build.dbFileName, self.build.buildName)
end)
else
local newBuildName = self.controls.importCodeBuildName.buf
local newFileName = main.buildPath .. newBuildName .. ".xml"
local file = io.open(newFileName, "r")
if file then
file:close()
main:OpenMessagePopup("Build Import", "A build with that name already exists.")
return
end
self:ImportToBuild(newFileName, newBuildName)
end
end)
self.controls.importCodeGo.enabled = function()
return self.importCodeState == "VALID" and (self.controls.importCodeMode.sel == 1 or self.controls.importCodeBuildName.buf:match("%S"))
end
end)
function ImportTabClass:Draw(viewPort, inputEvents)
self.x = viewPort.x
self.y = viewPort.y
self.width = viewPort.width
self.height = viewPort.height
self:ProcessControlsInput(inputEvents, viewPort)
main:DrawBackground(viewPort)
self:DrawControls(viewPort)
end
function ImportTabClass:DownloadCharacterList()
self.charImportMode = "DOWNLOADCHARLIST"
self.charImportStatus = "Retrieving character list..."
local accountName = self.controls.accountName.buf
local sessionID = #self.controls.sessionInput.buf == 32 and self.controls.sessionInput.buf or main.accountSessionIDs[accountName]
launch:DownloadPage("https://www.pathofexile.com/character-window/get-characters?accountName="..accountName, function(page, errMsg)
if errMsg then
self.charImportStatus = data.colorCodes.NEGATIVE.."Unknown error retrieving character list, try again ("..errMsg")"
self.charImportMode = "GETACCOUNTNAME"
return
elseif page == "false" then
self.charImportStatus = data.colorCodes.NEGATIVE.."Failed to retrieve character list."
self.charImportMode = "GETSESSIONID"
return
end
local charList, errMsg = self:ProcessJSON(page)
if errMsg then
self.charImportStatus = data.colorCodes.NEGATIVE.."Error processing character list, try again later"
self.charImportMode = "GETACCOUNTNAME"
return
end
self.charImportStatus = "Character list successfully retrieved."
self.charImportMode = "SELECTCHAR"
main.lastAccountName = accountName
if sessionID then
main.accountSessionIDs[accountName] = sessionID
end
wipeTable(self.controls.charSelect.list)
for i, char in ipairs(charList) do
t_insert(self.controls.charSelect.list, {
val = char,
label = string.format("%s: Level %d %s in %s", char.name or "?", char.level or 0, char.class or "?", char.league or "?")
})
end
table.sort(self.controls.charSelect.list, function(a,b)
return a.val.name:lower() < b.val.name:lower()
end)
end, sessionID and "POESESSID="..sessionID)
end
function ImportTabClass:DownloadPassiveTree()
self.charImportMode = "IMPORTING"
self.charImportStatus = "Retrieving character passive tree..."
local accountName = self.controls.accountName.buf
local sessionID = #self.controls.sessionInput.buf == 32 and self.controls.sessionInput.buf or main.accountSessionIDs[accountName]
local charSelect = self.controls.charSelect
local charData = charSelect.list[charSelect.sel].val
launch:DownloadPage("https://www.pathofexile.com/character-window/get-passive-skills?accountName="..accountName.."&character="..charData.name, function(page, errMsg)
self.charImportMode = "SELECTCHAR"
if errMsg then
self.charImportStatus = data.colorCodes.NEGATIVE.."Unknown error importing character data, try again ("..errMsg")"
return
elseif page == "false" then
self.charImportStatus = data.colorCodes.NEGATIVE.."Failed to retrieve character data, try again."
return
end
local passiveData, errMsg = self:ProcessJSON(page)
if errMsg then
self.charImportStatus = data.colorCodes.NEGATIVE.."Error processing character data, try again later."
return
end
self.charImportStatus = data.colorCodes.POSITIVE.."Passive tree successfully imported."
self.build.spec:ImportFromNodeList(charData.classId, charData.ascendancyClass, passiveData.hashes)
self.build.spec:AddUndoState()
self.build.characterLevel = charData.level
self.build.buildFlag = true
ConPrintTable(passiveData)
end, sessionID and "POESESSID="..sessionID)
end
function ImportTabClass:ProcessJSON(json)
local func, errMsg = loadstring("return "..jsonToLua(json))
if errMsg then
return nil, errMsg
end
setfenv(func, { }) -- Sandbox the function just in case
local data = func()
if type(data) ~= "table" then
return nil, "Return type is not a table"
end
return data
end
function ImportTabClass:ImportToBuild(buildFileName, buildName)
self.build:Shutdown()
local file = io.open(buildFileName, "w+")
if not file then
main:ShowMessagePopup("Build Import", "^xFF2222Error:^7 Couldn't create build file (invalid name?)")
return
end
file:write(self.importCodeXML)
file:close()
self.build:Init(buildFileName, buildName)
self.build.viewMode = "TREE"
end