diff --git a/.gitattributes b/.gitattributes
index 9a41934dc..96dc68a76 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,7 +8,7 @@
*.md linguist-detectable
# Compressonator
-*.a binary
+*.a binary
*.lib binary
# dmxpp
@@ -22,6 +22,9 @@
*.phy binary
*.vta binary
+# toolpp
+*.wc binary
+
# vicepp
*.dec binary
*.enc binary
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1506e0dcf..9522dc346 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,11 +16,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Options
option(SOURCEPP_USE_BSPPP "Build bsppp library" ON)
option(SOURCEPP_USE_DMXPP "Build dmxpp library" ON)
-option(SOURCEPP_USE_FGDPP "Build fgdpp library" ON)
option(SOURCEPP_USE_GAMEPP "Build gamepp library" ON)
option(SOURCEPP_USE_KVPP "Build kvpp library" ON)
option(SOURCEPP_USE_MDLPP "Build mdlpp library" ON)
option(SOURCEPP_USE_STEAMPP "Build steampp library" ON)
+option(SOURCEPP_USE_TOOLPP "Build toolpp library" ON)
option(SOURCEPP_USE_VICEPP "Build vicepp library" ON)
option(SOURCEPP_USE_VPKPP "Build vpkpp library" ON)
option(SOURCEPP_USE_VTFPP "Build vtfpp library" ON)
@@ -34,6 +34,9 @@ option(SOURCEPP_LINK_STATIC_MSVC_RUNTIME "Link to static MSVC runtime library"
if(SOURCEPP_USE_STEAMPP)
set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "")
endif()
+if(SOURCEPP_USE_TOOLPP)
+ set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "")
+endif()
if(SOURCEPP_USE_VPKPP)
set(SOURCEPP_USE_BSPPP ON CACHE INTERNAL "")
set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "")
@@ -89,11 +92,11 @@ endif()
# Add libraries
add_sourcepp_library(bsppp NO_TEST) # sourcepp::bsppp
add_sourcepp_library(dmxpp) # sourcepp::dmxpp
-add_sourcepp_library(fgdpp) # sourcepp::fgdpp
add_sourcepp_library(gamepp) # sourcepp::gamepp
add_sourcepp_library(kvpp) # sourcepp::kvpp
add_sourcepp_library(mdlpp) # sourcepp::mdlpp
add_sourcepp_library(steampp C) # sourcepp::steampp
+add_sourcepp_library(toolpp) # sourcepp::toolpp
add_sourcepp_library(vicepp C CSHARP) # sourcepp::vicepp
add_sourcepp_library(vpkpp C CSHARP NO_TEST) # sourcepp::vpkpp
add_sourcepp_library(vtfpp) # sourcepp::vtfpp
diff --git a/FUTURE.md b/FUTURE.md
index 34cb450c7..49f988de3 100644
--- a/FUTURE.md
+++ b/FUTURE.md
@@ -12,21 +12,18 @@
- Add support for v9+ DMX files
- Add support for keyvalues2 and keyvalues2_flat formats
- Add write support
-- `fgdpp`
- - Perhaps add the ability to parse TeamSpen's additions to the format?
- `gamepp`
- Add a function to create instances of a game rather than just finding existing ones
- When creating an instance of the game, attaching a console might be easier, or enabling -condebug,
which would then allow reading output from the console
- Add a method to take a screenshot of the game and move the file to a user-specified location
-- `kvpp`
- - Add write support
- `mdlpp`
- Parse animations/sequences
- Make something to construct StudioModel objects from a given model file like obj/glTF?
- Add a save method to write the constituent parts of a StudioModel to disk
+- `toolpp`
+ - Perhaps add the ability to parse TeamSpen's additions to the FGD format?
- `vpkpp`
- - Read/write LZMA-compressed zip files, and make sure it works correctly as a BSP paklump
- Cache file handles so they're not constantly getting closed/opened
- `vtfpp`
- Improve conversion speeds between formats that use handrolled per-pixel converters (SIMD? Compute shader?)
diff --git a/README.md b/README.md
index 39111d299..e7970d830 100644
--- a/README.md
+++ b/README.md
@@ -20,132 +20,188 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one
Write |
Wrappers |
+
- bsppp |
-
-
- |
+ bsppp |
+ BSP v17-27 |
✅ |
✅ |
- |
+ |
+
- dmxpp |
-
-
- |
+ dmxpp |
+ DMX Binary v1-5 |
✅ |
❌ |
- |
+ |
+
- fgdpp |
-
-
- |
+ gamepp |
+ Get Source engine instance window title/position/size |
✅ |
+ ❌ |
+ |
+
+
+
+ | Run commands in a Source engine instance remotely |
+ ❌ |
✅ |
- |
+
- gamepp |
-
-
- - Get Source engine instance window title/position/size
- - Run commands in a Source engine instance remotely
-
- |
- n/a |
- n/a |
- |
+ kvpp |
+ KeyValues v1* |
+ ✅ |
+ ✅ |
+ |
+
- kvpp |
-
-
- |
+ mdlpp |
+ MDL v44-49† |
✅ |
+ ❌ |
+ |
+
+
+
+ | VTX v7 |
✅ |
- |
+ ❌ |
+
- mdlpp |
-
-
- |
+ VVD v4 |
✅ |
❌ |
- |
+
- steampp |
-
-
- - Find Steam install folder
- - Find installed Steam games
-
- |
- n/a |
- n/a |
- C |
+ steampp |
+ Find Steam install folder |
+ ✅ |
+ - |
+ C |
+
+
+
+ | Find installed Steam games |
+ ✅ |
+ - |
+
- vicepp |
+ toolpp |
-
+ FGD (Source 1)
+ • Hammer++ modifications
+ • Strata Source modifications
|
✅ |
✅ |
- C C# |
+ |
+
- vpkpp |
-
- - BMZ
- - BSP v17-27
- - FPX v10 (Tactical Intervention)
- - GCF v6
- - GMA v1-3 (Garry's Mod)
- - PAK (Quake, WON Half-Life)
- - PCK v1-2 (Godot Engine)
- - PK3 (Quake III)
- - PK4 (Quake IV, Doom 3)
- - VPK v1-2
- - VPK (Vampire: The Masquerade - Bloodlines)
- - ZIP
-
+ WC (CmdSeq) v0.1-0.2
+ • Strata Source modifications
|
✅ |
✅ |
- C C# |
+
- vtfpp |
-
-
- |
+ vicepp |
+ VICE Encrypted Files |
+ ✅ |
+ ✅ |
+ C C# |
+
+
+
+ vpkpp |
+ BMZ |
+ ✅ |
+ ✅ |
+ C C# |
+
+
+
+ | BSP v17-27 |
+ ✅ |
+ ✅ |
+
+
+
+ | FPX v10 (Tactical Intervention) |
+ ✅ |
+ ✅ |
+
+
+
+ | GCF v6 |
+ ✅ |
+ ❌ |
+
+
+
+ | GMA v1-3 (Garry's Mod) |
+ ✅ |
+ ✅ |
+
+
+
+ | PAK (Quake, WON Half-Life) |
+ ✅ |
+ ✅ |
+
+
+
+ | PCK v1-2 (Godot Engine) |
+ ✅ |
+ ✅ |
+
+
+
+ | PK3 (Quake III) |
+ ✅ |
+ ✅ |
+
+
+
+ | PK4 (Quake IV, Doom 3) |
+ ✅ |
+ ✅ |
+
+
+
+ | VPK v1-2 |
+ ✅ |
+ ✅ |
+
+
+
+ | VPK (Vampire: The Masquerade - Bloodlines) |
+ ✅ |
+ ✅ |
+
+
+
+ | ZIP (and BZ2, GZ, XZ, ZSTD) |
+ ✅ |
+ ✅ |
+
+
+
+ vtfpp |
+ VTF v7.0-7.6 |
✅ |
❌ |
- |
+ |
diff --git a/include/sourcepp/String.h b/include/sourcepp/String.h
index edf7b570b..51c2703ef 100644
--- a/include/sourcepp/String.h
+++ b/include/sourcepp/String.h
@@ -58,11 +58,13 @@ void normalizeSlashes(std::string& path, bool stripSlashPrefix = false, bool str
void denormalizeSlashes(std::string& path, bool stripSlashPrefix = false, bool stripSlashSuffix = true);
-std::from_chars_result toInt(std::string_view number, std::integral auto& out, int base = 10) {
+std::from_chars_result toBool(std::string_view number, bool& out, int base = 10);
+
+inline std::from_chars_result toInt(std::string_view number, std::integral auto& out, int base = 10) {
return std::from_chars(number.data(), number.data() + number.size(), out, base);
}
-std::from_chars_result toFloat(std::string_view number, std::floating_point auto& out) {
+inline std::from_chars_result toFloat(std::string_view number, std::floating_point auto& out) {
#ifdef __APPLE__
// Piece of shit compiler
out = std::stof(std::string{number});
diff --git a/include/toolpp/CmdSeq.h b/include/toolpp/CmdSeq.h
new file mode 100644
index 000000000..8e69d9f19
--- /dev/null
+++ b/include/toolpp/CmdSeq.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include
+
+namespace toolpp {
+
+class CmdSeq {
+public:
+ struct Command {
+ bool enabled;
+
+ enum class Special : int32_t {
+ NONE = 0,
+ CHANGE_DIRECTORY = 256,
+ COPY_FILE = 257,
+ DELETE_FILE = 258,
+ RENAME_FILE = 259,
+ COPY_FILE_IF_EXISTS_ALT = 260,
+ COPY_FILE_IF_EXISTS = 261,
+ } special;
+ std::string executable;
+ std::string arguments;
+
+ bool ensureFileExists;
+ std::string pathToTheoreticallyExistingFile;
+
+ bool useProcessWindow;
+
+ bool waitForKeypress;
+ };
+
+ struct Sequence {
+ std::string name;
+ std::vector commands;
+ };
+
+ explicit CmdSeq(std::string path_);
+
+ [[nodiscard]] float getVersion() const;
+
+ void setVersion(bool isV02);
+
+ [[nodiscard]] std::vector& getSequences();
+
+ [[nodiscard]] const std::vector& getSequences() const;
+
+ [[nodiscard]] std::vector bake() const;
+
+ [[nodiscard]] std::vector bake(bool overrideUsingKeyValues) const;
+
+ bool bake(const std::string& path_);
+
+ bool bake(const std::string& path_, bool overrideUsingKeyValues);
+
+protected:
+ void parseBinary(const std::string& path);
+
+ void parseKeyValues(const std::string& path);
+
+ bool usingKeyValues = false;
+ float version;
+ std::string path;
+ std::vector sequences;
+};
+
+} // namespace toolpp
diff --git a/include/fgdpp/fgdpp.h b/include/toolpp/FGD.h
similarity index 97%
rename from include/fgdpp/fgdpp.h
rename to include/toolpp/FGD.h
index 42242ccda..ac39ecb68 100644
--- a/include/fgdpp/fgdpp.h
+++ b/include/toolpp/FGD.h
@@ -9,7 +9,7 @@
#include
#include
-namespace fgdpp {
+namespace toolpp {
class FGD {
public:
@@ -189,9 +189,9 @@ class FGDWriter {
EntityWriter beginEntity(const std::string& classType, const std::vector& classProperties, const std::string& name, const std::string& description);
- [[nodiscard]] std::string bakeToString();
+ [[nodiscard]] std::string bake();
- void bakeToFile(const std::string& fgdPath);
+ void bake(const std::string& fgdPath);
protected:
FGDWriter();
diff --git a/include/toolpp/toolpp.h b/include/toolpp/toolpp.h
new file mode 100644
index 000000000..2882a9537
--- /dev/null
+++ b/include/toolpp/toolpp.h
@@ -0,0 +1,9 @@
+#pragma once
+
+/*
+ * This header is just included so consumers of this library can
+ * include it the same way as any of the other SourcePP libraries.
+ */
+
+#include "CmdSeq.h"
+#include "FGD.h"
diff --git a/src/fgdpp/_fgdpp.cmake b/src/fgdpp/_fgdpp.cmake
deleted file mode 100644
index 1d8fc2571..000000000
--- a/src/fgdpp/_fgdpp.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-add_pretty_parser(fgdpp
- SOURCES
- "${CMAKE_CURRENT_SOURCE_DIR}/include/fgdpp/fgdpp.h"
- "${CMAKE_CURRENT_LIST_DIR}/fgdpp.cpp")
diff --git a/src/sourcepp/String.cpp b/src/sourcepp/String.cpp
index c014d7767..6f2ec66b6 100644
--- a/src/sourcepp/String.cpp
+++ b/src/sourcepp/String.cpp
@@ -177,3 +177,10 @@ void string::denormalizeSlashes(std::string& path, bool stripSlashPrefix, bool s
path.pop_back();
}
}
+
+std::from_chars_result string::toBool(std::string_view number, bool& out, int base) {
+ uint8_t tmp;
+ auto result = std::from_chars(number.data(), number.data() + number.size(), tmp, base);
+ out = tmp;
+ return result;
+}
diff --git a/src/toolpp/CmdSeq.cpp b/src/toolpp/CmdSeq.cpp
new file mode 100644
index 000000000..ba11869bc
--- /dev/null
+++ b/src/toolpp/CmdSeq.cpp
@@ -0,0 +1,207 @@
+#include
+
+#include
+
+#include
+#include
+#include
+
+using namespace kvpp;
+using namespace sourcepp;
+using namespace toolpp;
+
+namespace {
+
+std::vector bakeBinary(const CmdSeq& cmdSeq) {
+ std::vector out;
+ BufferStream writer{out};
+
+ writer
+ .write("Worldcraft Command Sequences\r\n\x1a", 31)
+ .write(cmdSeq.getVersion())
+ .write(cmdSeq.getSequences().size());
+
+ for (const auto& sequence : cmdSeq.getSequences()) {
+ writer
+ .write(sequence.name, true, 128)
+ .write(sequence.commands.size());
+
+ for (const auto& command : sequence.commands) {
+ writer
+ .write(command.enabled)
+ .write(command.special)
+ .write(command.executable, true, 260)
+ .write(command.arguments, true, 260)
+ .write(true)
+ .write(command.ensureFileExists)
+ .write(command.pathToTheoreticallyExistingFile, true, 260)
+ .write(command.useProcessWindow);
+
+ if (cmdSeq.getVersion() > 0.15f) {
+ writer.write(command.waitForKeypress);
+ }
+ }
+ }
+
+ out.resize(writer.size());
+ return out;
+}
+
+std::vector bakeKeyValues(const CmdSeq& cmdSeq) {
+ KV1Writer kv;
+ auto& kvFile = kv.addChild("Command Sequences");
+ for (const auto& sequence : cmdSeq.getSequences()) {
+ auto& kvSequence = kvFile.addChild(sequence.name);
+ for (int i = 1; i <= sequence.commands.size(); i++) {
+ const auto& command = sequence.commands[i - 1];
+ auto& kvCommand = kvSequence.addChild(std::to_string(i));
+ kvCommand["enabled"] = command.enabled;
+ kvCommand["special_cmd"] = static_cast(command.special);
+ kvCommand["run"] = command.executable;
+ kvCommand["params"] = command.arguments;
+ kvCommand["ensure_check"] = command.ensureFileExists;
+ kvCommand["ensure_fn"] = command.pathToTheoreticallyExistingFile;
+ kvCommand["use_process_wnd"] = command.useProcessWindow;
+ kvCommand["no_wait"] = command.waitForKeypress;
+ }
+ }
+
+ const auto kvStr = kv.bake();
+ std::vector out;
+ out.resize(kvStr.length());
+ std::memcpy(out.data(), kvStr.data(), kvStr.length());
+ return out;
+}
+
+} // namespace
+
+CmdSeq::CmdSeq(std::string path_)
+ : version(0.f)
+ , path(std::move(path_)) {
+ {
+ FileStream reader{path};
+ if (!reader) {
+ return;
+ }
+ if (auto binStr = reader.seek_in(0).read_string(10); binStr == "Worldcraft") {
+ this->usingKeyValues = false;
+ } else {
+ auto kvStr = reader.seek_in(0).read_string(19);
+ string::toLower(kvStr);
+ if (kvStr == "\"command sequences\"") {
+ this->usingKeyValues = true;
+ } else {
+ return;
+ }
+ }
+ }
+ if (this->usingKeyValues) {
+ this->parseKeyValues(path);
+ } else {
+ this->parseBinary(path);
+ }
+}
+
+float CmdSeq::getVersion() const {
+ return this->version;
+}
+
+void CmdSeq::setVersion(bool isV02) {
+ if (isV02) {
+ this->version = 0.2f;
+ } else {
+ this->version = 0.1f;
+ }
+}
+
+void CmdSeq::parseBinary(const std::string& path_) {
+ FileStream reader{path_};
+ if (!reader) {
+ return;
+ }
+
+ reader.seek_in(31).read(this->version);
+
+ auto sequenceCount = reader.read();
+ for (uint32_t s = 0; s < sequenceCount; s++) {
+ auto& sequence = this->sequences.emplace_back();
+ sequence.name = reader.read_string(128);
+
+ auto commandCount = reader.read();
+ for (uint32_t c = 0; c < commandCount; c++) {
+ auto& command = sequence.commands.emplace_back();
+ command.enabled = reader.read() & 0xFF;
+ command.special = reader.read();
+ command.executable = reader.read_string(260);
+ command.arguments = reader.read_string(260);
+ reader.skip_in();
+ command.ensureFileExists = reader.read();
+ command.pathToTheoreticallyExistingFile = reader.read_string(260);
+ command.useProcessWindow = reader.read();
+ if (version > 0.15f) {
+ command.waitForKeypress = reader.read();
+ }
+ }
+ }
+}
+
+void CmdSeq::parseKeyValues(const std::string& path_) {
+ this->version = 0.2f;
+
+ KV1 cmdSeq{fs::readFileText(path_)};
+ for (const auto& kvSequence : cmdSeq["Command Sequences"].getChildren()) {
+ auto& sequence = this->sequences.emplace_back();
+ sequence.name = kvSequence.getKey();
+
+ for (const auto& kvCommand : kvSequence.getChildren()) {
+ auto& command = sequence.commands.emplace_back();
+ string::toBool(kvCommand["enabled"].getValue(), command.enabled);
+ string::toInt(kvCommand["special_cmd"].getValue(), reinterpret_cast&>(command.special));
+ command.executable = kvCommand["run"].getValue();
+ command.arguments = kvCommand["params"].getValue();
+ string::toBool(kvCommand["ensure_check"].getValue(), command.ensureFileExists);
+ command.pathToTheoreticallyExistingFile = kvCommand["ensure_fn"].getValue();
+ string::toBool(kvCommand["use_process_wnd"].getValue(), command.useProcessWindow);
+ string::toBool(kvCommand["no_wait"].getValue(), command.waitForKeypress);
+ }
+ }
+}
+
+std::vector& CmdSeq::getSequences() {
+ return this->sequences;
+}
+
+const std::vector& CmdSeq::getSequences() const {
+ return this->sequences;
+}
+
+std::vector CmdSeq::bake() const {
+ return this->bake(this->usingKeyValues);
+}
+
+std::vector CmdSeq::bake(bool overrideUsingKeyValues) const {
+ if (overrideUsingKeyValues) {
+ return ::bakeKeyValues(*this);
+ }
+ return ::bakeBinary(*this);
+}
+
+bool CmdSeq::bake(const std::string& path_) {
+ return this->bake(path_, this->usingKeyValues);
+}
+
+bool CmdSeq::bake(const std::string& path_, bool overrideUsingKeyValues) {
+ FileStream writer{path_};
+ if (!writer) {
+ return false;
+ }
+ this->path = path_;
+
+ writer.seek_out(0);
+ if (overrideUsingKeyValues) {
+ writer.write(::bakeKeyValues(*this));
+ } else {
+ writer.write(::bakeBinary(*this));
+ }
+ return true;
+}
diff --git a/src/fgdpp/fgdpp.cpp b/src/toolpp/FGD.cpp
similarity index 99%
rename from src/fgdpp/fgdpp.cpp
rename to src/toolpp/FGD.cpp
index 6c2e59f38..3d2a3e098 100644
--- a/src/fgdpp/fgdpp.cpp
+++ b/src/toolpp/FGD.cpp
@@ -1,4 +1,4 @@
-#include
+#include
#include
#include
@@ -10,8 +10,8 @@
#include
#include
-using namespace fgdpp;
using namespace sourcepp;
+using namespace toolpp;
namespace {
@@ -829,7 +829,7 @@ FGDWriter& FGDWriter::EntityWriter::endEntity() {
return this->parent;
}
-std::string FGDWriter::bakeToString() {
+std::string FGDWriter::bake() {
this->backingData.resize(this->writer.tell());
if (this->backingData.ends_with("\n\n")) {
this->backingData.pop_back();
@@ -837,6 +837,6 @@ std::string FGDWriter::bakeToString() {
return this->backingData;
}
-void FGDWriter::bakeToFile(const std::string& fgdPath) {
- fs::writeFileText(fgdPath, this->bakeToString());
+void FGDWriter::bake(const std::string& fgdPath) {
+ fs::writeFileText(fgdPath, this->bake());
}
diff --git a/src/toolpp/_toolpp.cmake b/src/toolpp/_toolpp.cmake
new file mode 100644
index 000000000..d8d9342c1
--- /dev/null
+++ b/src/toolpp/_toolpp.cmake
@@ -0,0 +1,8 @@
+add_pretty_parser(toolpp
+ DEPS sourcepp::kvpp
+ SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/toolpp/CmdSeq.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/toolpp/FGD.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/toolpp/toolpp.h"
+ "${CMAKE_CURRENT_LIST_DIR}/CmdSeq.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/FGD.cpp")
diff --git a/test/kvpp.cpp b/test/kvpp.cpp
index 07a105a7b..051003ef2 100644
--- a/test/kvpp.cpp
+++ b/test/kvpp.cpp
@@ -174,7 +174,6 @@ TEST(kvpp, write_escaped) {
EXPECT_STREQ(kv1Writer["\"keys\""]["test\t2"].getValue().data(), "0\n");
EXPECT_TRUE(kv1Writer["\"keys\""]["test\t2"].getChildren().empty());
- kv1Writer.bake("test.txt");
KV1 kv1{kv1Writer.bake(), true};
ASSERT_EQ(kv1.getChildren().size(), 1);
diff --git a/test/res/toolpp/cmdseq/binary.wc b/test/res/toolpp/cmdseq/binary.wc
new file mode 100644
index 000000000..46e8ab51a
Binary files /dev/null and b/test/res/toolpp/cmdseq/binary.wc differ
diff --git a/test/res/toolpp/cmdseq/keyvalues.wc b/test/res/toolpp/cmdseq/keyvalues.wc
new file mode 100644
index 000000000..eaf404d54
--- /dev/null
+++ b/test/res/toolpp/cmdseq/keyvalues.wc
@@ -0,0 +1,279 @@
+"Command Sequences"
+{
+ "Fast"
+ {
+ "1"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$bsp_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "2"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$postcompiler_exe"
+ "params" "--propcombine $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "3"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$vis_exe"
+ "params" "-fast -game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "4"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$light_exe"
+ "params" "-fast -hdr -StaticPropLighting -StaticPropPolys -game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "5"
+ {
+ "enabled" "1"
+ "special_cmd" "257"
+ "run" ""
+ "params" "$path\\$file.bsp $bspdir\\$file.bsp"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "6"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$game_exe"
+ "params" "-dev -console -allowdebug -game $gamedir +map $file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "1"
+ }
+ }
+ "HDR Full Compile"
+ {
+ "1"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$bsp_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "2"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$postcompiler_exe"
+ "params" "--propcombine $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "3"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$vis_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "4"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$light_exe"
+ "params" "-hdr -StaticPropLighting -StaticPropPolys -game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "5"
+ {
+ "enabled" "1"
+ "special_cmd" "257"
+ "run" ""
+ "params" "$path\\$file.bsp $bspdir\\$file.bsp"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "6"
+ {
+ "enabled" "0"
+ "special_cmd" "0"
+ "run" "$game_exe"
+ "params" "-dev -console -allowdebug -game $gamedir +map $file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "1"
+ }
+ }
+ "HDR Portal Lighting Full Compile"
+ {
+ "1"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$bsp_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "2"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$postcompiler_exe"
+ "params" "--propcombine $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "3"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$vis_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "4"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$light_exe"
+ "params" "-hdr -StaticPropLighting -StaticPropPolys -PortalTraversalLighting -game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "5"
+ {
+ "enabled" "1"
+ "special_cmd" "257"
+ "run" ""
+ "params" "$path\\$file.bsp $bspdir\\$file.bsp"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "6"
+ {
+ "enabled" "0"
+ "special_cmd" "0"
+ "run" "$game_exe"
+ "params" "-dev -console -allowdebug -game $gamedir +map $file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "1"
+ }
+ }
+ "HDR Portal Lighting+AO Full Compile"
+ {
+ "1"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$bsp_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "2"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$postcompiler_exe"
+ "params" "--propcombine $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "3"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$vis_exe"
+ "params" "-game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "4"
+ {
+ "enabled" "1"
+ "special_cmd" "0"
+ "run" "$light_exe"
+ "params" "-hdr -StaticPropLighting -StaticPropPolys -PortalTraversalLighting -PortalTraversalAO -game $gamedir $path\\$file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "5"
+ {
+ "enabled" "1"
+ "special_cmd" "257"
+ "run" ""
+ "params" "$path\\$file.bsp $bspdir\\$file.bsp"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "0"
+ }
+ "6"
+ {
+ "enabled" "0"
+ "special_cmd" "0"
+ "run" "$game_exe"
+ "params" "-dev -console -allowdebug -game $gamedir +map $file"
+ "ensure_check" "0"
+ "ensure_fn" ""
+ "use_process_wnd" "1"
+ "no_wait" "1"
+ }
+ }
+}
diff --git a/test/res/fgdpp/empty.fgd b/test/res/toolpp/fgd/empty.fgd
similarity index 100%
rename from test/res/fgdpp/empty.fgd
rename to test/res/toolpp/fgd/empty.fgd
diff --git a/test/res/fgdpp/game/base.fgd b/test/res/toolpp/fgd/game/base.fgd
similarity index 100%
rename from test/res/fgdpp/game/base.fgd
rename to test/res/toolpp/fgd/game/base.fgd
diff --git a/test/res/fgdpp/game/halflife2.fgd b/test/res/toolpp/fgd/game/halflife2.fgd
similarity index 100%
rename from test/res/fgdpp/game/halflife2.fgd
rename to test/res/toolpp/fgd/game/halflife2.fgd
diff --git a/test/res/fgdpp/game/portal.fgd b/test/res/toolpp/fgd/game/portal.fgd
similarity index 100%
rename from test/res/fgdpp/game/portal.fgd
rename to test/res/toolpp/fgd/game/portal.fgd
diff --git a/test/res/fgdpp/game/portal2.fgd b/test/res/toolpp/fgd/game/portal2.fgd
similarity index 100%
rename from test/res/fgdpp/game/portal2.fgd
rename to test/res/toolpp/fgd/game/portal2.fgd
diff --git a/test/res/fgdpp/ideal.fgd b/test/res/toolpp/fgd/ideal.fgd
similarity index 100%
rename from test/res/fgdpp/ideal.fgd
rename to test/res/toolpp/fgd/ideal.fgd
diff --git a/test/fgdpp.cpp b/test/toolpp.cpp
similarity index 81%
rename from test/fgdpp.cpp
rename to test/toolpp.cpp
index 9ea0dedda..19ff0830c 100644
--- a/test/fgdpp.cpp
+++ b/test/toolpp.cpp
@@ -1,11 +1,37 @@
#include
-#include
+#include
+#include
-using namespace fgdpp;
+using namespace sourcepp;
+using namespace toolpp;
-TEST(fgdpp, parseEmpty) {
- FGD fgd{ASSET_ROOT "fgdpp/empty.fgd"};
+TEST(toolpp, cmdSeqOpenBinary) {
+ CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/binary.wc"};
+ ASSERT_EQ(cmdSeq.getSequences().size(), 8);
+}
+
+TEST(toolpp, cmdSeqOpenKeyValues) {
+ CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/keyvalues.wc"};
+ ASSERT_EQ(cmdSeq.getSequences().size(), 4);
+}
+
+TEST(toolpp, cmdSeqBakeBinary) {
+ CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/binary.wc"};
+ auto existingData = fs::readFileBuffer(ASSET_ROOT "toolpp/cmdseq/binary.wc");
+ auto bakedData = cmdSeq.bake();
+ ASSERT_EQ(existingData, bakedData);
+}
+
+TEST(toolpp, cmdSeqBakeKeyValues) {
+ CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/keyvalues.wc"};
+ auto existingData = fs::readFileBuffer(ASSET_ROOT "toolpp/cmdseq/keyvalues.wc");
+ auto bakedData = cmdSeq.bake();
+ ASSERT_EQ(existingData, bakedData);
+}
+
+TEST(toolpp, fgdParseEmpty) {
+ FGD fgd{ASSET_ROOT "toolpp/fgd/empty.fgd"};
EXPECT_EQ(fgd.getVersion(), 0);
EXPECT_EQ(fgd.getMapSize()[0], 0);
EXPECT_EQ(fgd.getMapSize()[1], 0);
@@ -14,8 +40,8 @@ TEST(fgdpp, parseEmpty) {
EXPECT_TRUE(fgd.getAutoVisGroups().empty());
}
-TEST(fgdpp, parseIdeal) {
- FGD fgd{ASSET_ROOT "fgdpp/ideal.fgd"};
+TEST(toolpp, fgdParseIdeal) {
+ FGD fgd{ASSET_ROOT "toolpp/fgd/ideal.fgd"};
EXPECT_EQ(fgd.getVersion(), 8);
EXPECT_EQ(fgd.getMapSize()[0], -16384);
EXPECT_EQ(fgd.getMapSize()[1], 16384);
@@ -24,8 +50,8 @@ TEST(fgdpp, parseIdeal) {
EXPECT_EQ(fgd.getAutoVisGroups().size(), 3);
}
-TEST(fgdpp, parsePortal2) {
- FGD fgd{ASSET_ROOT "fgdpp/game/portal2.fgd"};
+TEST(toolpp, fgdParsePortal2) {
+ FGD fgd{ASSET_ROOT "toolpp/fgd/game/portal2.fgd"};
EXPECT_EQ(fgd.getVersion(), 0);
EXPECT_EQ(fgd.getMapSize()[0], -16384);
EXPECT_EQ(fgd.getMapSize()[1], 16384);
@@ -34,7 +60,7 @@ TEST(fgdpp, parsePortal2) {
EXPECT_TRUE(fgd.getAutoVisGroups().empty());
}
-TEST(fgdpp, write) {
+TEST(toolpp, fgdWrite) {
std::string writeContents = FGDWriter::begin()
.version(8)
.mapSize({-16384, 16384})
@@ -103,7 +129,7 @@ TEST(fgdpp, write) {
"func_viscluster",
})
.endAutoVisGroup()
- .bakeToString();
+ .bake();
std::string expectedContents = R"~(@version(8)