SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
PakLump.cpp
Go to the documentation of this file.
1#include <bsppp/PakLump.h>
2
3#include <filesystem>
4
5#include <bsppp/BSP.h>
6#include <FileStream.h>
7#include <mz.h>
8#include <mz_zip.h>
9#include <sourcepp/FS.h>
10#include <sourcepp/String.h>
11
12using namespace bsppp;
13using namespace sourcepp;
14using namespace vpkpp;
15
16PakLump::PakLump(const std::string& fullFilePath_)
17 : ZIP(fullFilePath_)
18 , tempPakLumpPath((std::filesystem::temp_directory_path() / (string::generateUUIDv4() + ".zip")).string()) {}
19
21 // Pull this in from the ZIP dtor, have to do it before deleting the file
22 this->closeZIP();
23 std::filesystem::remove(this->tempPakLumpPath);
24}
25
26std::unique_ptr<PackFile> PakLump::open(const std::string& path, const EntryCallback& callback) {
27 if (!std::filesystem::exists(path)) {
28 // File does not exist
29 return nullptr;
30 }
31
32 auto* bsp = new PakLump{path};
33 auto packFile = std::unique_ptr<PackFile>(bsp);
34
35 {
36 bsppp::BSP reader{path};
37 if (!reader) {
38 // File failed to load, or has an invalid signature
39 return nullptr;
40 }
41
42 bsp->version = reader.getVersion();
43 bsp->mapRevision = reader.getMapRevision();
44
45 if (auto pakFileLump = reader.getLumpData(BSPLump::PAKFILE)) {
46 // Extract the paklump to a temp file
47 FileStream writer{bsp->tempPakLumpPath, FileStream::OPT_TRUNCATE | FileStream::OPT_CREATE_IF_NONEXISTENT};
48 writer.write(*pakFileLump);
49 } else {
50 // No paklump, create an empty zip
51 if (!ZIP::create(bsp->tempPakLumpPath)) {
52 return nullptr;
53 }
54 }
55 }
56
57 if (!bsp->openZIP(bsp->tempPakLumpPath)) {
58 return nullptr;
59 }
60
61 for (auto code = mz_zip_goto_first_entry(bsp->zipHandle); code == MZ_OK; code = mz_zip_goto_next_entry(bsp->zipHandle)) {
62 mz_zip_file* fileInfo = nullptr;
63 if (mz_zip_entry_get_info(bsp->zipHandle, &fileInfo)) {
64 return nullptr;
65 }
66 if (mz_zip_entry_is_dir(bsp->zipHandle) == MZ_OK) {
67 continue;
68 }
69
70 auto entryPath = bsp->cleanEntryPath(fileInfo->filename);
71
72 Entry entry = createNewEntry();
73 entry.flags = fileInfo->compression_method << 16;
74 entry.length = fileInfo->uncompressed_size;
75 entry.compressedLength = fileInfo->compressed_size;
76 entry.crc32 = fileInfo->crc;
77
78 bsp->entries.emplace(entryPath, entry);
79
80 if (callback) {
81 callback(entryPath, entry);
82 }
83 }
84
85 return packFile;
86}
87
88bool PakLump::bake(const std::string& outputDir_, BakeOptions options, const EntryCallback& callback) {
89 // Get the proper file output folder
90 const std::string outputDir = this->getBakeOutputDir(outputDir_);
91 const std::string outputPath = outputDir + '/' + this->getFilename();
92
93 // If the output path is different, copy the entire BSP there
94 if (outputPath != this->fullFilePath) {
95 std::filesystem::copy_file(this->fullFilePath, outputPath, std::filesystem::copy_options::overwrite_existing);
97 }
98
99 // Use temp folder so we can read from the current ZIP
100 if (!this->bakeTempZip(this->tempZIPPath, options, callback)) {
101 return false;
102 }
103 this->mergeUnbakedEntries();
104
105 // Close the ZIP
106 this->closeZIP();
107
108 // Write the new lump
109 {
110 bsppp::BSP writer{this->fullFilePath};
111 if (!writer) {
112 return false;
113 }
114 writer.setLump(BSPLump::PAKFILE, 0, fs::readFileBuffer(this->tempZIPPath));
115 writer.bake();
116 }
117
118 // Rename and reopen the ZIP
119 std::filesystem::rename(this->tempZIPPath, this->tempPakLumpPath);
120 return this->openZIP(this->tempPakLumpPath);
121}
122
123PakLump::operator std::string() const {
124 return PackFile::operator std::string() +
125 " | Version v" + std::to_string(this->version) +
126 " | Map Revision " + std::to_string(this->mapRevision);
127}
uint32_t getVersion() const
Definition: BSP.cpp:92
Utility class for vpkpp integration - you need to include this header in a C++ file somewhere in your...
Definition: PakLump.h:13
PakLump(const std::string &fullFilePath_)
Definition: PakLump.cpp:16
bool bake(const std::string &outputDir_, vpkpp::BakeOptions options, const EntryCallback &callback) override
If output folder is an empty string, it will overwrite the original.
Definition: PakLump.cpp:88
static std::unique_ptr< PackFile > open(const std::string &path, const EntryCallback &callback=nullptr)
Open a BSP file.
Definition: PakLump.cpp:26
const std::string tempPakLumpPath
Definition: PakLump.h:37
~PakLump() override
Definition: PakLump.cpp:20
This class represents the metadata that a file has inside a PackFile.
Definition: Entry.h:14
uint32_t flags
Format-specific flags (PCK: File flags, VPK: Internal parser state, ZIP: Compression method / strengt...
Definition: Entry.h:19
uint64_t compressedLength
If the format supports compression, this is the compressed length.
Definition: Entry.h:30
uint32_t crc32
CRC32 checksum - 0 if unused.
Definition: Entry.h:40
uint64_t length
Length in bytes (in formats with compression, this is the uncompressed length)
Definition: Entry.h:26
EntryCallbackBase< void > EntryCallback
Definition: PackFile.h:30
void mergeUnbakedEntries()
Definition: PackFile.cpp:656
std::string fullFilePath
Definition: PackFile.h:219
std::string getFilename() const
/home/user/pak01_dir.vpk -> pak01_dir.vpk
Definition: PackFile.cpp:591
std::string getBakeOutputDir(const std::string &outputDir) const
Definition: PackFile.cpp:640
void setFullFilePath(const std::string &outputDir)
Definition: PackFile.cpp:672
static Entry createNewEntry()
Definition: PackFile.cpp:686
Definition: ZIP.h:15
const std::string tempZIPPath
Definition: ZIP.h:66
void closeZIP()
Definition: ZIP.cpp:265
bool openZIP(std::string_view path)
Definition: ZIP.cpp:247
bool bakeTempZip(const std::string &writeZipPath, BakeOptions options, const EntryCallback &callback) const
Definition: ZIP.cpp:181
static std::unique_ptr< PackFile > create(const std::string &path)
Create a ZIP file.
Definition: ZIP.cpp:29
Definition: BSP.h:18
std::vector< std::byte > readFileBuffer(const std::string &filepath, std::size_t startOffset=0)
Definition: FS.cpp:9
Definition: LZMA.h:11
Definition: Attribute.h:5