Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/API/BuildOps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ function M.remove_gem(params)
return true
end


-- params: { path: string }
function M.save_build(params)
if not build or not build.SaveDB then
Expand All @@ -637,8 +636,7 @@ function M.save_build(params)
end

-- Sync curAscendClassName from the current ascendClassId so the Build XML
-- element always reflects the live state (guards against stale names after
-- set_tree or new_build with a different ascendancy).
-- element reflects the live state after set_tree/new_build operations.
if build.spec and build.spec.curClass and build.spec.curClass.classes then
local ascendId = build.spec.curAscendClassId or 0
local ascendClass = build.spec.curClass.classes[ascendId] or build.spec.curClass.classes[0]
Expand All @@ -647,11 +645,7 @@ function M.save_build(params)
end
end

-- Re-process all socket groups so that gem modifications made via add_gem /
-- set_gem_level / set_gem_quality are fully resolved before SaveDB serialises
-- the skillsTab. ProcessSocketGroup populates gemData / grantedEffect from
-- the current gemId/nameSpec, ensuring accurate gemId and nameSpec values in
-- the output XML.
-- Resolve socket group gem metadata before SaveDB serialises skills.
if build.skillsTab and build.skillsTab.socketGroupList then
for _, socketGroup in ipairs(build.skillsTab.socketGroupList) do
if build.skillsTab.ProcessSocketGroup then
Expand Down
121 changes: 121 additions & 0 deletions src/API/Handlers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,127 @@ handlers.save_build = function(params)
return { ok = true, result = res }
end

local function import_status_success(status, successText)
return type(status) == 'string' and status:find(successText, 1, true) ~= nil
end

local function import_status_error(status, fallback)
if type(status) ~= 'string' or #status == 0 then
return fallback
end
-- Strip PoB colour escapes before returning the status over JSON-RPC.
return (status:gsub('%^x%x%x%x%x%x%x', ''):gsub('%^%d', ''))
end

-- Import character passive tree + jewels from PoE official API JSON.
-- Caller fetches /character-window/get-passive-skills and forwards the raw
-- response body as params.json. params.char_data carries character metadata
-- required by ImportTab.lua (name, level, class, league).
handlers.import_passive_tree = function(params)
if not _G.build or not _G.build.importTab then
return { ok = false, error = 'no build loaded - call load_build_xml or new_build first' }
end
if not params or type(params.json) ~= 'string' or #params.json == 0 then
return { ok = false, error = 'missing or empty json' }
end
if type(params.char_data) ~= 'table' then
return { ok = false, error = 'missing char_data (need at least name, level, class, league)' }
end

local importTab = _G.build.importTab
if params.clear_jewels ~= nil and importTab.controls and importTab.controls.charImportTreeClearJewels then
importTab.controls.charImportTreeClearJewels.state = params.clear_jewels and true or false
end

local ok, err = pcall(function()
importTab:ImportPassiveTreeAndJewels(params.json, params.char_data)
end)
if not ok then
return { ok = false, error = 'ImportPassiveTreeAndJewels failed: ' .. tostring(err) }
end
if not import_status_success(importTab.charImportStatus, 'Passive tree and jewels successfully imported') then
return {
ok = false,
error = 'ImportPassiveTreeAndJewels failed: ' .. import_status_error(importTab.charImportStatus, 'import did not report success'),
}
end

return {
ok = true,
status = importTab.charImportStatus,
level = _G.build.characterLevel,
className = _G.build.spec and _G.build.spec.curClassName or nil,
ascendClassName = _G.build.spec and _G.build.spec.curAscendClassName or nil,
}
end

-- Import character items + skill gems from PoE official API JSON.
-- params.json is the raw body of /character-window/get-items.
handlers.import_items_skills = function(params)
if not _G.build or not _G.build.importTab then
return { ok = false, error = 'no build loaded - call load_build_xml or new_build first' }
end
if not params or type(params.json) ~= 'string' or #params.json == 0 then
return { ok = false, error = 'missing or empty json' }
end

local importTab = _G.build.importTab
local controls = importTab.controls or {}
if params.clear_items ~= nil and controls.charImportItemsClearItems then
controls.charImportItemsClearItems.state = params.clear_items and true or false
end
if params.clear_skills ~= nil and controls.charImportItemsClearSkills then
controls.charImportItemsClearSkills.state = params.clear_skills and true or false
end
if params.ignore_weapon_swap ~= nil and controls.charImportItemsIgnoreWeaponSwap then
controls.charImportItemsIgnoreWeaponSwap.state = params.ignore_weapon_swap and true or false
end

local ok, ret = pcall(function()
return importTab:ImportItemsAndSkills(params.json)
end)
if not ok then
return { ok = false, error = 'ImportItemsAndSkills failed: ' .. tostring(ret) }
end
if not import_status_success(importTab.charImportStatus, 'Items and skills successfully imported') then
return {
ok = false,
error = 'ImportItemsAndSkills failed: ' .. import_status_error(importTab.charImportStatus, 'import did not report success'),
}
end

-- The PoE API returns the character's currently active inventory under
-- "Weapon"/"Offhand" and the swap set under "Weapon2"/"Offhand2".
-- ImportTab maps those to primary and swap slots but does not update
-- useSecondWeaponSet. Unless swap import is intentionally ignored, force the
-- active item set back to primary slots so immediate calculations match the
-- live character's active weapons.
if not (params.ignore_weapon_swap and true or false) and _G.build.itemsTab and _G.build.itemsTab.activeItemSet then
_G.build.itemsTab.activeItemSet.useSecondWeaponSet = false
if _G.build.itemsTab.AddUndoState then
pcall(function() _G.build.itemsTab:AddUndoState() end)
end
_G.build.buildFlag = true
end

local character = nil
if type(ret) == 'table' then
character = {
name = ret.name,
level = ret.level,
class = ret.class,
league = ret.league,
}
end

return {
ok = true,
status = importTab.charImportStatus,
level = _G.build.characterLevel,
character = character,
}
end

return {
handlers = handlers,
version_meta = version_meta,
Expand Down