Skip to content

Improve headless mode: implement Inflate/Deflate, NewFileSearch, and path resolution#9748

Open
Saturate wants to merge 1 commit intoPathOfBuildingCommunity:devfrom
Saturate:headless-inflate-filesearch-paths
Open

Improve headless mode: implement Inflate/Deflate, NewFileSearch, and path resolution#9748
Saturate wants to merge 1 commit intoPathOfBuildingCommunity:devfrom
Saturate:headless-inflate-filesearch-paths

Conversation

@Saturate
Copy link
Copy Markdown

Builds on #9505 and #9507.

Description of the problem being solved:

Headless mode has three stub functions that prevent full build analysis:

  1. Inflate/Deflate return "" so timeless jewel data (zlib-compressed .zip files) can't be loaded. Breaks any build using Elegant Hubris, Lethal Pride, Brutal Restraint, Militant Faith, or Glorious Vanity.
  2. NewFileSearch returns nil so file existence checks fail, preventing the .bin cache path from working.
  3. GetScriptPath()/GetRuntimePath()/GetUserPath() return "" so data file paths resolve incorrectly.

Additionally, package.path doesn't include runtime/lua/ in headless mode, so require("xml") and other runtime modules fail.

This PR implements all three in HeadlessWrapper.lua only, no core PoB files modified:

  • Inflate/Deflate: LuaJIT FFI binding to system zlib (zlib1.dll on Windows, libz.so.1 on Linux, libz.1.dylib on macOS). Falls back to empty-string stubs if zlib isn't found.
  • NewFileSearch: Supports exact paths and glob patterns. Uses dir /b on Windows, ls on Unix. Returns objects with GetFileName(), GetFileModifiedTime(), NextFile().
  • Path resolution: Uses debug.getinfo(1, 'S').source to resolve the script directory. Cross-platform, no subprocess spawn (improves on io.popen("pwd") from Fix headless path helpers for relative data loads #9507).
  • UTF-8 fallback: Intercepts require("lua-utf8") and falls back to a pure-Lua stub when the native module isn't available.
  • Stdio API activation: Gated behind POB_API_STDIO=1 env var or --stdio CLI flag. Loads API/Server.lua from Add headless JSON-RPC API for programmatic PoB access #9505.

Steps taken to verify a working solution:

  • Loaded a build with Elegant Hubris timeless jewel via loadBuildFromJSON. Data decompressed correctly, .bin cache written, no crash.
  • Calculated stats match poe.ninja pre-calculated values exactly (cold resist, life, attributes all correct with Supreme Ostentation applied).
  • JSON-RPC API server starts and responds to ping/quit.
  • Tested on macOS arm64, LuaJIT 2.1, zlib 1.2.12.

Link to a build that showcases this PR:

Any build using a timeless jewel. Tested with a Holy Relic Necromancer using Elegant Hubris (Supreme Ostentation).

Before screenshot:

N/A (headless mode, no UI)

After screenshot:

N/A (headless mode, no UI)

…path resolution

- Inflate/Deflate via LuaJIT FFI + system zlib (Windows, Linux, macOS)
- NewFileSearch with glob support (dir /b on Windows, ls on Unix)
- Path resolution via debug.getinfo instead of empty strings
- Add runtime/lua/ to package.path for headless module loading
- UTF-8 require fallback for headless mode
- Stdio JSON-RPC API activation via POB_API_STDIO=1 env var
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant