SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
BSP.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <optional>
6#include <span>
7#include <string>
8#include <tuple>
9#include <vector>
10#include <unordered_map>
11
13
14#include "EntityLump.h"
15#include "LumpData.h"
16#include "PakLump.h"
17
18namespace bsppp {
19
22
23enum class BSPLump : int32_t {
24 UNKNOWN = -1,
25 ENTITIES = 0,
26 PLANES,
27 TEXDATA,
30 NODES,
31 TEXINFO,
32 FACES,
35 LEAFS,
36 FACEIDS,
37 EDGES,
39 MODELS,
43 BRUSHES,
45 AREAS,
74 PAKFILE,
105
106 COUNT,
107};
108constexpr int32_t BSP_LUMP_COUNT = 64;
109static_assert(static_cast<std::underlying_type_t<BSPLump>>(BSPLump::COUNT) == BSP_LUMP_COUNT, "Incorrect lump count!");
110
113constexpr std::array<uint32_t, 64> BSP_LUMP_ORDER{
114 25, 24, 32, 57, 49, 59, 6, 2,
115 43, 44, 10, 17, 1, 18, 19, 14,
116 5, 20, 21, 4, 0, 29, 26, 62,
117 3, 12, 13, 7, 58, 33, 48, 63,
118 28, 9, 8, 53, 37, 38, 39, 30,
119 31, 56, 52, 51, 55, 16, 36, 45,
120 50, 60, 61, 46, 42, 41, 54, 15,
121 34, 47, 11, 22, 23, 27, 35, 40,
122};
123
124class BSP {
125 struct Lump {
127 uint32_t offset;
129 uint32_t length;
131 uint32_t version;
133 uint32_t uncompressedLength;
134 };
135
136 struct Header {
138 uint32_t version;
140 std::array<Lump, BSP_LUMP_COUNT> lumps;
142 uint32_t mapRevision;
143 };
144
145public:
146 explicit BSP(std::string path_, bool loadPatchFiles = true);
147
148 explicit operator bool() const;
149
150 static BSP create(std::string path, uint32_t version = 21, uint32_t mapRevision = 0);
151
152 [[nodiscard]] uint32_t getVersion() const;
153
154 void setVersion(uint32_t version);
155
156 [[nodiscard]] uint32_t getMapRevision() const;
157
158 void setMapRevision(uint32_t mapRevision);
159
160 [[nodiscard]] bool isL4D2() const;
161
162 void setL4D2(bool isL4D2);
163
164 [[nodiscard]] bool isConsole() const;
165
166 void setConsole(bool isConsole);
167
168 [[nodiscard]] bool hasLump(BSPLump lumpIndex) const;
169
170 [[nodiscard]] bool isLumpCompressed(BSPLump lumpIndex) const;
171
172 [[nodiscard]] uint32_t getLumpVersion(BSPLump lumpIndex) const;
173
174 [[nodiscard]] std::optional<std::vector<std::byte>> getLumpData(BSPLump lumpIndex, bool noDecompression = false) const;
175
176 template<BSPLump Lump>
177 [[nodiscard]] auto getLumpData() const {
178 if constexpr (Lump == BSPLump::ENTITIES) {
179 return this->parseEntities();
180 } else if constexpr (Lump == BSPLump::PLANES) {
181 return this->parsePlanes();
182 } else if constexpr (Lump == BSPLump::TEXDATA) {
183 return this->parseTextureData();
184 } else if constexpr (Lump == BSPLump::VERTEXES) {
185 return this->parseVertices();
186 } else if constexpr (Lump == BSPLump::NODES) {
187 return this->parseNodes();
188 } else if constexpr (Lump == BSPLump::TEXINFO) {
189 return this->parseTextureInfo();
190 } else if constexpr (Lump == BSPLump::FACES) {
191 return this->parseFaces();
192 } else if constexpr (Lump == BSPLump::EDGES) {
193 return this->parseEdges();
194 } else if constexpr (Lump == BSPLump::SURFEDGES) {
195 return this->parseSurfEdges();
196 } else if constexpr (Lump == BSPLump::MODELS) {
197 return this->parseBrushModels();
198 } else if constexpr (Lump == BSPLump::ORIGINALFACES) {
199 return this->parseOriginalFaces();
200 } else if constexpr (Lump == BSPLump::GAME_LUMP) {
201 return this->parseGameLumps(true);
202 } else {
203 return this->getLumpData(Lump);
204 }
205 }
206
210 bool setLump(BSPLump lumpIndex, uint32_t version, std::span<const std::byte> data, uint8_t compressLevel = 0);
211
212 bool setLump(uint32_t version, std::span<const BSPEntityKeyValues> data, uint8_t compressLevel = 0);
213
214 [[nodiscard]] bool isGameLumpCompressed(BSPGameLump::Signature signature) const;
215
216 [[nodiscard]] uint16_t getGameLumpVersion(BSPGameLump::Signature signature);
217
218 [[nodiscard]] std::optional<std::vector<std::byte>> getGameLumpData(BSPGameLump::Signature signature) const;
219
220 bool setGameLump(BSPGameLump::Signature signature, uint16_t version, std::span<const std::byte> data, uint8_t compressLevel = 0);
221
223 void resetLump(BSPLump lumpIndex);
224
226 void reset();
227
228 void createLumpPatchFile(BSPLump lumpIndex) const;
229
230 bool setLumpFromPatchFile(const std::string& lumpFilePath);
231
232 bool bake(std::string_view outputPath = "");
233
234protected:
235 bool readHeader();
236
237 [[nodiscard]] std::vector<BSPEntityKeyValues> parseEntities() const;
238
239 [[nodiscard]] std::vector<BSPPlane> parsePlanes() const;
240
241 [[nodiscard]] std::vector<BSPTextureData> parseTextureData() const;
242
243 [[nodiscard]] std::vector<BSPVertex> parseVertices() const;
244
245 [[nodiscard]] std::vector<BSPNode> parseNodes() const;
246
247 [[nodiscard]] std::vector<BSPTextureInfo> parseTextureInfo() const;
248
249 [[nodiscard]] std::vector<BSPFace> parseFaces() const;
250
251 [[nodiscard]] std::vector<BSPEdge> parseEdges() const;
252
253 [[nodiscard]] std::vector<BSPSurfEdge> parseSurfEdges() const;
254
255 [[nodiscard]] std::vector<BSPBrushModel> parseBrushModels() const;
256
257 [[nodiscard]] std::vector<BSPFace> parseOriginalFaces() const;
258
259 [[nodiscard]] std::vector<BSPGameLump> parseGameLumps(bool decompress) const;
260
261 std::string path;
262 Header header{};
263
264 uint32_t stagedVersion{};
265 std::unordered_map<uint32_t, std::pair<Lump, std::vector<std::byte>>> stagedLumps;
266 std::vector<BSPGameLump> stagedGameLumps;
268
269 // Slightly different header despite using the same version just to be quirky
270 bool l4d2 = false;
271 // BSP is mostly big-endian
272 bool console = false;
273};
274
275} // namespace bsppp
Header header
Definition: BSP.h:262
auto getLumpData() const
Definition: BSP.h:177
uint32_t getVersion() const
Definition: BSP.cpp:92
bool hasLump(BSPLump lumpIndex) const
Definition: BSP.cpp:124
std::vector< BSPBrushModel > parseBrushModels() const
Definition: BSP.cpp:694
bool console
Definition: BSP.h:272
std::vector< BSPNode > parseNodes() const
Definition: BSP.cpp:656
std::vector< BSPTextureData > parseTextureData() const
Definition: BSP.cpp:648
std::vector< BSPGameLump > parseGameLumps(bool decompress) const
Definition: BSP.cpp:709
std::unordered_map< uint32_t, std::pair< Lump, std::vector< std::byte > > > stagedLumps
Definition: BSP.h:265
std::vector< BSPFace > parseOriginalFaces() const
Definition: BSP.cpp:698
void setL4D2(bool isL4D2)
Definition: BSP.cpp:112
static BSP create(std::string path, uint32_t version=21, uint32_t mapRevision=0)
Definition: BSP.cpp:73
bool isLumpCompressed(BSPLump lumpIndex) const
Definition: BSP.cpp:133
uint32_t stagedVersion
Definition: BSP.h:264
void reset()
Resets ALL in-memory modifications (version, all lumps including game lumps, map revision)
Definition: BSP.cpp:294
void setConsole(bool isConsole)
Definition: BSP.cpp:120
bool bake(std::string_view outputPath="")
Definition: BSP.cpp:364
void resetLump(BSPLump lumpIndex)
Reset changes made to a lump before they're written to disk.
Definition: BSP.cpp:276
uint32_t getMapRevision() const
Definition: BSP.cpp:100
std::vector< BSPGameLump > stagedGameLumps
Definition: BSP.h:266
bool setGameLump(BSPGameLump::Signature signature, uint16_t version, std::span< const std::byte > data, uint8_t compressLevel=0)
Definition: BSP.cpp:253
std::vector< BSPFace > parseFaces() const
Definition: BSP.cpp:670
uint32_t stagedMapRevision
Definition: BSP.h:267
void setVersion(uint32_t version)
Definition: BSP.cpp:96
std::vector< BSPSurfEdge > parseSurfEdges() const
Definition: BSP.cpp:690
std::optional< std::vector< std::byte > > getGameLumpData(BSPGameLump::Signature signature) const
Definition: BSP.cpp:241
uint16_t getGameLumpVersion(BSPGameLump::Signature signature)
Definition: BSP.cpp:232
bool isL4D2() const
Definition: BSP.cpp:108
std::vector< BSPEdge > parseEdges() const
Definition: BSP.cpp:680
std::vector< BSPVertex > parseVertices() const
Definition: BSP.cpp:652
void createLumpPatchFile(BSPLump lumpIndex) const
Definition: BSP.cpp:304
bool readHeader()
Definition: BSP.cpp:525
uint32_t getLumpVersion(BSPLump lumpIndex) const
Definition: BSP.cpp:142
bool isGameLumpCompressed(BSPGameLump::Signature signature) const
Definition: BSP.cpp:223
bool l4d2
Definition: BSP.h:270
std::vector< BSPPlane > parsePlanes() const
Definition: BSP.cpp:644
bool setLumpFromPatchFile(const std::string &lumpFilePath)
Definition: BSP.cpp:342
std::string path
Definition: BSP.h:261
bool setLump(BSPLump lumpIndex, uint32_t version, std::span< const std::byte > data, uint8_t compressLevel=0)
BSP::setGameLump should be used for writing game lumps as they need special handling.
Definition: BSP.cpp:176
bool isConsole() const
Definition: BSP.cpp:116
std::vector< BSPTextureInfo > parseTextureInfo() const
Definition: BSP.cpp:666
std::vector< BSPEntityKeyValues > parseEntities() const
Definition: BSP.cpp:577
void setMapRevision(uint32_t mapRevision)
Definition: BSP.cpp:104
Definition: BSP.h:18
constexpr std::array< uint32_t, 64 > BSP_LUMP_ORDER
Pulled from Portal 2, map e1912.
Definition: BSP.h:113
constexpr auto BSP_SIGNATURE
Definition: BSP.h:20
constexpr int32_t BSP_LUMP_COUNT
Definition: BSP.h:108
BSPLump
Definition: BSP.h:23
@ S2006_XBOX_LIGHTMAPPAGEINFOS
@ S2004_DISP_LIGHTMAP_ALPHAS
@ DISP_LIGHTMAP_SAMPLE_POSITIONS
constexpr auto BSP_CONSOLE_SIGNATURE
Definition: BSP.h:21
consteval uint32_t makeFourCC(const char fourCC[4])
Creates a FourCC identifier from a string of 4 characters.
Definition: Binary.h:18