| 284 | } |
| 285 | |
| 286 | std::string StudioApp::extractVirtualFile(const FileEntry& entry) |
| 287 | { |
| 288 | if (!entry.isVirtual()) |
| 289 | return entry.fullPath; |
| 290 | if (!tempExtractedFile.empty()) |
| 291 | { |
| 292 | std::error_code ec; |
| 293 | std::filesystem::remove(tempExtractedFile, ec); |
| 294 | tempExtractedFile.clear(); |
| 295 | } |
| 296 | |
| 297 | try |
| 298 | { |
| 299 | QFBank bank; |
| 300 | std::string bankName = StripPboExtension(entry.pboPath); |
| 301 | if (!bank.open(RString(bankName.c_str()))) |
| 302 | { |
| 303 | log("Failed to open PBO: " + entry.pboPath); |
| 304 | return {}; |
| 305 | } |
| 306 | bank.Lock(); |
| 307 | if (bank.error()) |
| 308 | { |
| 309 | log("PBO load error: " + entry.pboPath); |
| 310 | return {}; |
| 311 | } |
| 312 | |
| 313 | Ref<IFileBuffer> data = bank.Read(entry.pboFilename.c_str()); |
| 314 | if (!data || data->GetSize() == 0) |
| 315 | { |
| 316 | log("Failed to read from PBO: " + entry.pboFilename); |
| 317 | return {}; |
| 318 | } |
| 319 | auto tempDir = std::filesystem::temp_directory_path(); |
| 320 | std::string ext = entry.extension; |
| 321 | tempExtractedFile = (tempDir / ("poseidon_studio_tmp" + ext)).string(); |
| 322 | std::ofstream out(tempExtractedFile, std::ios::binary); |
| 323 | out.write(static_cast<const char*>(data->GetData()), data->GetSize()); |
| 324 | out.close(); |
| 325 | |
| 326 | return tempExtractedFile; |
| 327 | } |
| 328 | catch (const std::exception& e) |
| 329 | { |
| 330 | log("Extract error: " + std::string(e.what())); |
| 331 | return {}; |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | std::string StudioApp::resolveFilePath(const FileEntry& entry) |
| 336 | { |
nothing calls this directly
no test coverage detected