From 5079c739164aafe30419e3e579500f5a074dfd37 Mon Sep 17 00:00:00 2001 From: craftablescience Date: Sat, 24 Aug 2024 05:56:21 -0400 Subject: [PATCH 1/7] feat(toolpp): add CmdSeq.wc parser --- CMakeLists.txt | 5 + FUTURE.md | 1 - README.md | 13 +- include/sourcepp/String.h | 6 +- include/toolpp/CmdSeq.h | 53 +++++++ include/toolpp/toolpp.h | 8 + src/sourcepp/String.cpp | 7 + src/toolpp/CmdSeq.cpp | 90 +++++++++++ src/toolpp/_toolpp.cmake | 6 + test/res/toolpp/binary.wc | Bin 0 -> 25215 bytes test/res/toolpp/keyvalues.wc | 286 +++++++++++++++++++++++++++++++++++ test/toolpp.cpp | 15 ++ 12 files changed, 486 insertions(+), 4 deletions(-) create mode 100644 include/toolpp/CmdSeq.h create mode 100644 include/toolpp/toolpp.h create mode 100644 src/toolpp/CmdSeq.cpp create mode 100644 src/toolpp/_toolpp.cmake create mode 100644 test/res/toolpp/binary.wc create mode 100644 test/res/toolpp/keyvalues.wc create mode 100644 test/toolpp.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1506e0dcf..878ad3012 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option(SOURCEPP_USE_GAMEPP "Build gamepp library" 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 +35,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 "") @@ -94,6 +98,7 @@ 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..cb7feb3ed 100644 --- a/FUTURE.md +++ b/FUTURE.md @@ -26,7 +26,6 @@ - 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 - `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..fabf12547 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ✅ ❌ - + steampp @@ -103,6 +103,17 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one n/a C + + toolpp + + + + ✅ + ❌ + + vicepp 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..40e2038d4 --- /dev/null +++ b/include/toolpp/CmdSeq.h @@ -0,0 +1,53 @@ +#pragma once + +#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(const std::string& path); + + [[nodiscard]] const std::vector& getSequences() const; + +protected: + void parseBinary(const std::string& path); + + void parseKeyValues(const std::string& path); + + std::vector sequences; +}; + +} // namespace toolpp diff --git a/include/toolpp/toolpp.h b/include/toolpp/toolpp.h new file mode 100644 index 000000000..411364fec --- /dev/null +++ b/include/toolpp/toolpp.h @@ -0,0 +1,8 @@ +#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" 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..9678f4e0a --- /dev/null +++ b/src/toolpp/CmdSeq.cpp @@ -0,0 +1,90 @@ +#include + +#include +#include +#include + +using namespace kvpp; +using namespace sourcepp; +using namespace toolpp; + +CmdSeq::CmdSeq(const std::string& path) { + bool isBinary; + { + FileStream reader{path}; + if (!reader) { + return; + } + if (auto binStr = reader.seek_in(0).read_string(10); binStr == "Worldcraft") { + isBinary = true; + } else { + auto kvStr = reader.seek_in(0).read_string(19); + string::toLower(kvStr); + if (kvStr == "\"command sequences\"") { + isBinary = false; + } else { + return; + } + } + } + if (isBinary) { + this->parseBinary(path); + } else { + this->parseKeyValues(path); + } +} + +void CmdSeq::parseBinary(const std::string& path) { + FileStream reader{path}; + if (!reader) { + return; + } + + auto version = reader.seek_in(31).read(); + + 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) { + 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); + } + } +} + +const std::vector& CmdSeq::getSequences() const { + return this->sequences; +} diff --git a/src/toolpp/_toolpp.cmake b/src/toolpp/_toolpp.cmake new file mode 100644 index 000000000..28b274d87 --- /dev/null +++ b/src/toolpp/_toolpp.cmake @@ -0,0 +1,6 @@ +add_pretty_parser(toolpp + DEPS sourcepp::kvpp + SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/include/toolpp/CmdSeq.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/toolpp/toolpp.h" + "${CMAKE_CURRENT_LIST_DIR}/CmdSeq.cpp") diff --git a/test/res/toolpp/binary.wc b/test/res/toolpp/binary.wc new file mode 100644 index 0000000000000000000000000000000000000000..eb4de6124a1c38b07842fe8e99b14238287378b9 GIT binary patch literal 25215 zcmeHO&2G~`5Z($Qek6DRPD_;osB%SnWoV9;@$_$_A=< z@%+{0?}HCdg%BTA5>>i{)@ruL@U+$X63$i_(o(@aDS<)3pkRv|C z6vD%Lpmeo&LB2q{0lPgjzL5LAJT2$@-b${vA@!7)e?rn#Qv-YEU*=RV;limw{pVoF z7i6bdxZhz!1hJaPnP9RtihwNmP9nF8Nnb~q+_7DLebDZD&~3uQgC4{k-8}jN|MsJz z6ql>pST|@-=nO@z&?dad_0Sv4(*_gd3$m;m2oWUk(3%ZqEv7X7bG1cyaCLmkjEj6h zmURQ*$cd?7i9qhkAT#Q`%p?B@LwHyQORkmK|RY>$Y9;TRp2i%E}J8G8S4fR zM;6r$9A4TaTr2@4XHT8R4;bC&OkYTqm1&u(Vg&-iBe(~e7p^w|o*I}Cn2%zyG|$Ne z1Hyx|=${+8n_#a=yp;9^!y-fo{nXL zff`1Lal~ec%@OQp-Czmb zpeZ^PTwiLV%Dp!7q^%pAm~tqCB+Vi%-xS)My?%So!)D!}?ck1gBGwJsuJYp3jabIN zOYPDPyubtwl5pY8fI9|Cz97rG0pxpjD8C^h+=YIy{t_MGp#wVJ93o$!W!<2jcGe9z zj@So*c*oDi4Z5u2d$-S}H>QKD+tleV8j9 z4)tz`i+!@(PL%>)F|SI2?gQt8c?vvjra>-T6RrgPz}yL~k9pdDI-x%r zo}Q%{tRSjbkZqrQPoJ2lZN~=1+2Z_kREuYxwlRVJXzTFufa>?!XLf(u>pt9hly&&F zdsv6(yw^qqJ+sJi{T}3;T))Tfh89VP8)R9B2ae3v?`f{zvmoPLlemGFb@+PvS%>Fb Y%YG2p9Kn9p_gIHV91t$B&0Fn{zh4M`w*UYD literal 0 HcmV?d00001 diff --git a/test/res/toolpp/keyvalues.wc b/test/res/toolpp/keyvalues.wc new file mode 100644 index 000000000..8f4aa0496 --- /dev/null +++ b/test/res/toolpp/keyvalues.wc @@ -0,0 +1,286 @@ +"Command Sequences" +{ + // Special commands (for special_cmd): + // 256 - Change Directory + // 257 - Copy File + // 258 - Delete File + // 259 - Rename File + // 261 - Copy File if it exists + // And they have no "run" string + "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" // Copy File + "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" // All game_exe things apparently have no wait, but it isn't used so whatever + } + } + "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" // Copy File + "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" // All game_exe things apparently have no wait, but it isn't used so whatever + } + } + "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" // Copy File + "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" // All game_exe things apparently have no wait, but it isn't used so whatever + } + } + "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" // Copy File + "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" // All game_exe things apparently have no wait, but it isn't used so whatever + } + } +} diff --git a/test/toolpp.cpp b/test/toolpp.cpp new file mode 100644 index 000000000..89316e6bf --- /dev/null +++ b/test/toolpp.cpp @@ -0,0 +1,15 @@ +#include + +#include + +using namespace toolpp; + +TEST(toolpp, openBinary) { + CmdSeq cmdSeq{ASSET_ROOT "toolpp/binary.wc"}; + ASSERT_EQ(cmdSeq.getSequences().size(), 8); +} + +TEST(toolpp, openKeyValues) { + CmdSeq cmdSeq{ASSET_ROOT "toolpp/keyvalues.wc"}; + ASSERT_EQ(cmdSeq.getSequences().size(), 4); +} From 0ce610b325d8522cd0e454d98b002a2191919b24 Mon Sep 17 00:00:00 2001 From: craftablescience Date: Sat, 24 Aug 2024 18:04:55 -0400 Subject: [PATCH 2/7] feat(fgdpp,toolpp): move FGD parser/writer into toolpp library --- CMakeLists.txt | 2 - include/{fgdpp/fgdpp.h => toolpp/FGD.h} | 6 +- include/toolpp/toolpp.h | 1 + src/fgdpp/_fgdpp.cmake | 4 - src/{fgdpp/fgdpp.cpp => toolpp/FGD.cpp} | 10 +- src/toolpp/_toolpp.cmake | 4 +- test/fgdpp.cpp | 192 ----------------- test/res/toolpp/{ => cmdseq}/binary.wc | Bin test/res/toolpp/{ => cmdseq}/keyvalues.wc | 0 test/res/{fgdpp => toolpp/fgd}/empty.fgd | 0 test/res/{fgdpp => toolpp/fgd}/game/base.fgd | 0 .../{fgdpp => toolpp/fgd}/game/halflife2.fgd | 0 .../res/{fgdpp => toolpp/fgd}/game/portal.fgd | 0 .../{fgdpp => toolpp/fgd}/game/portal2.fgd | 0 test/res/{fgdpp => toolpp/fgd}/ideal.fgd | 0 test/toolpp.cpp | 195 +++++++++++++++++- 16 files changed, 203 insertions(+), 211 deletions(-) rename include/{fgdpp/fgdpp.h => toolpp/FGD.h} (97%) delete mode 100644 src/fgdpp/_fgdpp.cmake rename src/{fgdpp/fgdpp.cpp => toolpp/FGD.cpp} (99%) delete mode 100644 test/fgdpp.cpp rename test/res/toolpp/{ => cmdseq}/binary.wc (100%) rename test/res/toolpp/{ => cmdseq}/keyvalues.wc (100%) rename test/res/{fgdpp => toolpp/fgd}/empty.fgd (100%) rename test/res/{fgdpp => toolpp/fgd}/game/base.fgd (100%) rename test/res/{fgdpp => toolpp/fgd}/game/halflife2.fgd (100%) rename test/res/{fgdpp => toolpp/fgd}/game/portal.fgd (100%) rename test/res/{fgdpp => toolpp/fgd}/game/portal2.fgd (100%) rename test/res/{fgdpp => toolpp/fgd}/ideal.fgd (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 878ad3012..9522dc346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ 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) @@ -93,7 +92,6 @@ 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 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 index 411364fec..2882a9537 100644 --- a/include/toolpp/toolpp.h +++ b/include/toolpp/toolpp.h @@ -6,3 +6,4 @@ */ #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/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 index 28b274d87..d8d9342c1 100644 --- a/src/toolpp/_toolpp.cmake +++ b/src/toolpp/_toolpp.cmake @@ -2,5 +2,7 @@ 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}/CmdSeq.cpp" + "${CMAKE_CURRENT_LIST_DIR}/FGD.cpp") diff --git a/test/fgdpp.cpp b/test/fgdpp.cpp deleted file mode 100644 index 9ea0dedda..000000000 --- a/test/fgdpp.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include - -#include - -using namespace fgdpp; - -TEST(fgdpp, parseEmpty) { - FGD fgd{ASSET_ROOT "fgdpp/empty.fgd"}; - EXPECT_EQ(fgd.getVersion(), 0); - EXPECT_EQ(fgd.getMapSize()[0], 0); - EXPECT_EQ(fgd.getMapSize()[1], 0); - EXPECT_TRUE(fgd.getEntities().empty()); - EXPECT_TRUE(fgd.getMaterialExclusionDirs().empty()); - EXPECT_TRUE(fgd.getAutoVisGroups().empty()); -} - -TEST(fgdpp, parseIdeal) { - FGD fgd{ASSET_ROOT "fgdpp/ideal.fgd"}; - EXPECT_EQ(fgd.getVersion(), 8); - EXPECT_EQ(fgd.getMapSize()[0], -16384); - EXPECT_EQ(fgd.getMapSize()[1], 16384); - EXPECT_EQ(fgd.getEntities().size(), 1); - EXPECT_EQ(fgd.getMaterialExclusionDirs().size(), 9); - EXPECT_EQ(fgd.getAutoVisGroups().size(), 3); -} - -TEST(fgdpp, parsePortal2) { - FGD fgd{ASSET_ROOT "fgdpp/game/portal2.fgd"}; - EXPECT_EQ(fgd.getVersion(), 0); - EXPECT_EQ(fgd.getMapSize()[0], -16384); - EXPECT_EQ(fgd.getMapSize()[1], 16384); - EXPECT_EQ(fgd.getEntities().size(), 494); - EXPECT_TRUE(fgd.getMaterialExclusionDirs().empty()); - EXPECT_TRUE(fgd.getAutoVisGroups().empty()); -} - -TEST(fgdpp, write) { - std::string writeContents = FGDWriter::begin() - .version(8) - .mapSize({-16384, 16384}) - .beginEntity( - "PointClass", - { - "base(Targetname, Angles, Origin)", - "halfgridsnap", - "studio(\"path/model space dot mdl\")", - }, - "entity_name", - "An entity that can be linked to another door and create a passage between them dynamically.") - .keyValue("portal1", "int", "", "", "", true) - .keyValue("portal2", "int", "Portal 2") - .keyValue("portal3", "int", "Portal 3", "0") - .keyValue("portal4", "int", "Portal 4", "0", "This is the wonderful world of Portal 4", false, true) - .input("portalInput1", "string") - .input("portalInput2", "string", "Portal Input 2") - .output("portalOutput1", "string") - .output("portalOutput2", "string", "Portal Output 2") - .beginKeyValueFlags("spawn_flags") - .flag(1, "something clever", true, "This flag is clever") - .flag(2, "something else", false, "This flag is something else") - .flag(4, "you said what now?", false) - .flag(8, "nothing", true) - .endKeyValueFlags() - .beginKeyValueChoices("model", "Model used", "models/something02.mdl", "", true, true) - .choice("models/something01.mdl", "something") - .choice("models/something02.mdl", "something else (default)") - .choice("models/something03.mdl", "something completely different") - .endKeyValueChoices() - .endEntity() - .beginEntity("ExtendClass", {}, "entity_name", "") - .keyValue("portal4", "void", "Portal 4 but better") - .output("portalOutput3", "string", "Portal Output 3") - .beginKeyValueFlags("effects", "Effects", "These sure are effects") - .flag(0, "None", false) - .flag(1, "Always, very expensive!", false) - .flag(2, "Bright, dynamic light at entity origin", false) - .flag(4, "Dim, dynamic light at entity origin", false) - .endKeyValueFlags() - .endEntity() - .materialExclusionDirs({ - "console", - "debug", - "engine", - "hud", - "perftest/gman", - "perftest/loader", - "vgui", - "voice", - "vr", - }) - .beginAutoVisGroup("Brushes") - .visGroup("Triggers", { - "trigger_once", - "trigger_multiple", - }) - .visGroup("Tool Brushes", { - "func_areaportal", - "func_viscluster", - }) - .endAutoVisGroup() - .beginAutoVisGroup("Tool Brushes") - .visGroup("Vis Clusters", { - "func_viscluster", - }) - .endAutoVisGroup() - .bakeToString(); - - std::string expectedContents = R"~(@version(8) - -@mapsize(-16384, 16384) - -@PointClass - base(Targetname, Angles, Origin) - halfgridsnap - studio("path/model space dot mdl") -= entity_name : - "An entity that can be linked to another door and create a passage between them dynamically." -[ - portal1(int) readonly - portal2(int) : "Portal 2" - portal3(int) : "Portal 3" : "0" - portal4(int) report : "Portal 4" : "0" : "This is the wonderful world of Portal 4" - input portalInput1(string) - input portalInput2(string) : "Portal Input 2" - output portalOutput1(string) - output portalOutput2(string) : "Portal Output 2" - spawn_flags(flags) = - [ - 1 : "something clever" : 1 : "This flag is clever" - 2 : "something else" : 0 : "This flag is something else" - 4 : "you said what now?" : 0 - 8 : "nothing" : 1 - ] - model(choices) readonly report : "Model used" : "models/something02.mdl" = - [ - "models/something01.mdl" : "something" - "models/something02.mdl" : "something else (default)" - "models/something03.mdl" : "something completely different" - ] -] - -@ExtendClass = entity_name : "" -[ - portal4(void) : "Portal 4 but better" - output portalOutput3(string) : "Portal Output 3" - effects(flags) : "Effects" : "These sure are effects" = - [ - 0 : "None" : 0 - 1 : "Always, very expensive!" : 0 - 2 : "Bright, dynamic light at entity origin" : 0 - 4 : "Dim, dynamic light at entity origin" : 0 - ] -] - -@MaterialExclusion -[ - "console" - "debug" - "engine" - "hud" - "perftest/gman" - "perftest/loader" - "vgui" - "voice" - "vr" -] - -@AutoVisGroup = "Brushes" -[ - "Triggers" - [ - "trigger_once" - "trigger_multiple" - ] - "Tool Brushes" - [ - "func_areaportal" - "func_viscluster" - ] -] - -@AutoVisGroup = "Tool Brushes" -[ - "Vis Clusters" - [ - "func_viscluster" - ] -] -)~"; - - EXPECT_STREQ(writeContents.c_str(), expectedContents.c_str()); -} diff --git a/test/res/toolpp/binary.wc b/test/res/toolpp/cmdseq/binary.wc similarity index 100% rename from test/res/toolpp/binary.wc rename to test/res/toolpp/cmdseq/binary.wc diff --git a/test/res/toolpp/keyvalues.wc b/test/res/toolpp/cmdseq/keyvalues.wc similarity index 100% rename from test/res/toolpp/keyvalues.wc rename to test/res/toolpp/cmdseq/keyvalues.wc 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/toolpp.cpp b/test/toolpp.cpp index 89316e6bf..a72a64b69 100644 --- a/test/toolpp.cpp +++ b/test/toolpp.cpp @@ -4,12 +4,199 @@ using namespace toolpp; -TEST(toolpp, openBinary) { - CmdSeq cmdSeq{ASSET_ROOT "toolpp/binary.wc"}; +TEST(toolpp, cmdSeqOpenBinary) { + CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/binary.wc"}; ASSERT_EQ(cmdSeq.getSequences().size(), 8); } -TEST(toolpp, openKeyValues) { - CmdSeq cmdSeq{ASSET_ROOT "toolpp/keyvalues.wc"}; +TEST(toolpp, cmdSeqOpenKeyValues) { + CmdSeq cmdSeq{ASSET_ROOT "toolpp/cmdseq/keyvalues.wc"}; ASSERT_EQ(cmdSeq.getSequences().size(), 4); } + +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); + EXPECT_TRUE(fgd.getEntities().empty()); + EXPECT_TRUE(fgd.getMaterialExclusionDirs().empty()); + EXPECT_TRUE(fgd.getAutoVisGroups().empty()); +} + +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); + EXPECT_EQ(fgd.getEntities().size(), 1); + EXPECT_EQ(fgd.getMaterialExclusionDirs().size(), 9); + EXPECT_EQ(fgd.getAutoVisGroups().size(), 3); +} + +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); + EXPECT_EQ(fgd.getEntities().size(), 494); + EXPECT_TRUE(fgd.getMaterialExclusionDirs().empty()); + EXPECT_TRUE(fgd.getAutoVisGroups().empty()); +} + +TEST(toolpp, fgdWrite) { + std::string writeContents = FGDWriter::begin() + .version(8) + .mapSize({-16384, 16384}) + .beginEntity( + "PointClass", + { + "base(Targetname, Angles, Origin)", + "halfgridsnap", + "studio(\"path/model space dot mdl\")", + }, + "entity_name", + "An entity that can be linked to another door and create a passage between them dynamically.") + .keyValue("portal1", "int", "", "", "", true) + .keyValue("portal2", "int", "Portal 2") + .keyValue("portal3", "int", "Portal 3", "0") + .keyValue("portal4", "int", "Portal 4", "0", "This is the wonderful world of Portal 4", false, true) + .input("portalInput1", "string") + .input("portalInput2", "string", "Portal Input 2") + .output("portalOutput1", "string") + .output("portalOutput2", "string", "Portal Output 2") + .beginKeyValueFlags("spawn_flags") + .flag(1, "something clever", true, "This flag is clever") + .flag(2, "something else", false, "This flag is something else") + .flag(4, "you said what now?", false) + .flag(8, "nothing", true) + .endKeyValueFlags() + .beginKeyValueChoices("model", "Model used", "models/something02.mdl", "", true, true) + .choice("models/something01.mdl", "something") + .choice("models/something02.mdl", "something else (default)") + .choice("models/something03.mdl", "something completely different") + .endKeyValueChoices() + .endEntity() + .beginEntity("ExtendClass", {}, "entity_name", "") + .keyValue("portal4", "void", "Portal 4 but better") + .output("portalOutput3", "string", "Portal Output 3") + .beginKeyValueFlags("effects", "Effects", "These sure are effects") + .flag(0, "None", false) + .flag(1, "Always, very expensive!", false) + .flag(2, "Bright, dynamic light at entity origin", false) + .flag(4, "Dim, dynamic light at entity origin", false) + .endKeyValueFlags() + .endEntity() + .materialExclusionDirs({ + "console", + "debug", + "engine", + "hud", + "perftest/gman", + "perftest/loader", + "vgui", + "voice", + "vr", + }) + .beginAutoVisGroup("Brushes") + .visGroup("Triggers", { + "trigger_once", + "trigger_multiple", + }) + .visGroup("Tool Brushes", { + "func_areaportal", + "func_viscluster", + }) + .endAutoVisGroup() + .beginAutoVisGroup("Tool Brushes") + .visGroup("Vis Clusters", { + "func_viscluster", + }) + .endAutoVisGroup() + .bake(); + + std::string expectedContents = R"~(@version(8) + +@mapsize(-16384, 16384) + +@PointClass + base(Targetname, Angles, Origin) + halfgridsnap + studio("path/model space dot mdl") += entity_name : + "An entity that can be linked to another door and create a passage between them dynamically." +[ + portal1(int) readonly + portal2(int) : "Portal 2" + portal3(int) : "Portal 3" : "0" + portal4(int) report : "Portal 4" : "0" : "This is the wonderful world of Portal 4" + input portalInput1(string) + input portalInput2(string) : "Portal Input 2" + output portalOutput1(string) + output portalOutput2(string) : "Portal Output 2" + spawn_flags(flags) = + [ + 1 : "something clever" : 1 : "This flag is clever" + 2 : "something else" : 0 : "This flag is something else" + 4 : "you said what now?" : 0 + 8 : "nothing" : 1 + ] + model(choices) readonly report : "Model used" : "models/something02.mdl" = + [ + "models/something01.mdl" : "something" + "models/something02.mdl" : "something else (default)" + "models/something03.mdl" : "something completely different" + ] +] + +@ExtendClass = entity_name : "" +[ + portal4(void) : "Portal 4 but better" + output portalOutput3(string) : "Portal Output 3" + effects(flags) : "Effects" : "These sure are effects" = + [ + 0 : "None" : 0 + 1 : "Always, very expensive!" : 0 + 2 : "Bright, dynamic light at entity origin" : 0 + 4 : "Dim, dynamic light at entity origin" : 0 + ] +] + +@MaterialExclusion +[ + "console" + "debug" + "engine" + "hud" + "perftest/gman" + "perftest/loader" + "vgui" + "voice" + "vr" +] + +@AutoVisGroup = "Brushes" +[ + "Triggers" + [ + "trigger_once" + "trigger_multiple" + ] + "Tool Brushes" + [ + "func_areaportal" + "func_viscluster" + ] +] + +@AutoVisGroup = "Tool Brushes" +[ + "Vis Clusters" + [ + "func_viscluster" + ] +] +)~"; + + EXPECT_STREQ(writeContents.c_str(), expectedContents.c_str()); +} From b45b87ef88404c825d00b3b1b998a93170e4736f Mon Sep 17 00:00:00 2001 From: craftablescience Date: Sat, 24 Aug 2024 18:05:07 -0400 Subject: [PATCH 3/7] chore: reformat table in readme --- README.md | 210 +++++++++++++++++++++++++++++------------------------- 1 file changed, 113 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index fabf12547..1eead32a9 100644 --- a/README.md +++ b/README.md @@ -21,142 +21,158 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Wrappers - bsppp - -
    -
  • BSP v17-27
  • -
- + bsppp + BSP v17-27 ✅ ✅ - + - dmxpp - -
    -
  • DMX Binary v1-5
  • -
- + 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 - toolpp + Find installed Steam games + ✅ + - + + + toolpp -
    -
  • WC v0.1-0.2
  • -
+ FGD (Source 1) +
Hammer++ FGD modifications +
Strata Source FGD modifications ✅ + ✅ + + + + WC (Command Sequences) v0.1-0.2 + ✅ ❌ - - + - vicepp - -
    -
  • VICE Encrypted Files
  • -
- + vicepp + VICE Encrypted Files ✅ ✅ - C
C# + 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
  • -
- + vpkpp + BMZ ✅ ✅ - C
C# + C
C# - vtfpp - -
    -
  • VTF v7.0-7.6
  • -
- + 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 ✅ ❌ - + From 2c5a8e36d42b025c275e2ceb497c34e04f1b0ea2 Mon Sep 17 00:00:00 2001 From: craftablescience Date: Sat, 24 Aug 2024 18:39:57 -0400 Subject: [PATCH 4/7] chore: remove bg highlighting from table in readme --- README.md | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1eead32a9..269b4322f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Write Wrappers + bsppp BSP v17-27 @@ -27,6 +28,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ✅ + dmxpp DMX Binary v1-5 @@ -34,18 +36,21 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ❌ + - gamepp + gamepp Get Source engine instance window title/position/size ✅ ❌ - + + Run commands in a Source engine instance remotely ❌ ✅ + kvpp KeyValues v1* @@ -53,37 +58,43 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ✅ + - mdlpp + mdlpp MDL v44-49 ✅ ❌ - + + VTX v7 ✅ ❌ + VVD v4 ✅ ❌ + - steampp + steampp Find Steam install folder ✅ - - C + C + Find installed Steam games ✅ - + - toolpp + toolpp FGD (Source 1)
Hammer++ FGD modifications @@ -91,13 +102,15 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ✅ ✅ - + + WC (Command Sequences) v0.1-0.2 ✅ ❌ + vicepp VICE Encrypted Files @@ -105,68 +118,81 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one ✅ C
C# + - vpkpp + vpkpp BMZ ✅ ✅ - C
C# + 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 From f1a03750981b69a671fae99d971f12d305a3578d Mon Sep 17 00:00:00 2001 From: craftablescience Date: Sat, 24 Aug 2024 23:37:40 -0400 Subject: [PATCH 5/7] feat(toolpp): add support for writing cmdseq files --- .gitattributes | 5 +- FUTURE.md | 5 +- README.md | 11 +- include/toolpp/CmdSeq.h | 20 +- src/toolpp/CmdSeq.cpp | 139 ++++++- test/kvpp.cpp | 1 - test/res/toolpp/cmdseq/binary.wc | Bin 25215 -> 25215 bytes test/res/toolpp/cmdseq/keyvalues.wc | 559 ++++++++++++++-------------- test/toolpp.cpp | 16 + 9 files changed, 453 insertions(+), 303 deletions(-) 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/FUTURE.md b/FUTURE.md index cb7feb3ed..3227de884 100644 --- a/FUTURE.md +++ b/FUTURE.md @@ -12,8 +12,6 @@ - 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, @@ -25,6 +23,9 @@ - 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` + - Add write support to KV1 `CmdSeq.wc` files when `kvpp` write support is implemented + - Perhaps add the ability to parse TeamSpen's additions to the FGD format? - `vpkpp` - Cache file handles so they're not constantly getting closed/opened - `vtfpp` diff --git a/README.md b/README.md index 269b4322f..4ecf574a6 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,8 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one toolpp FGD (Source 1) -
Hammer++ FGD modifications -
Strata Source FGD modifications +
Hammer++ modifications +
Strata Source modifications ✅ ✅ @@ -106,9 +106,12 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one - WC (Command Sequences) v0.1-0.2 + + WC (CmdSeq) v0.1-0.2 +
Strata Source modifications + + ✅ ✅ - ❌ diff --git a/include/toolpp/CmdSeq.h b/include/toolpp/CmdSeq.h index 40e2038d4..8e69d9f19 100644 --- a/include/toolpp/CmdSeq.h +++ b/include/toolpp/CmdSeq.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -38,15 +39,32 @@ class CmdSeq { std::vector commands; }; - explicit CmdSeq(const std::string& path); + 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; }; diff --git a/src/toolpp/CmdSeq.cpp b/src/toolpp/CmdSeq.cpp index 9678f4e0a..ba11869bc 100644 --- a/src/toolpp/CmdSeq.cpp +++ b/src/toolpp/CmdSeq.cpp @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -8,39 +10,117 @@ using namespace kvpp; using namespace sourcepp; using namespace toolpp; -CmdSeq::CmdSeq(const std::string& path) { - bool isBinary; +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") { - isBinary = true; + this->usingKeyValues = false; } else { auto kvStr = reader.seek_in(0).read_string(19); string::toLower(kvStr); if (kvStr == "\"command sequences\"") { - isBinary = false; + this->usingKeyValues = true; } else { return; } } } - if (isBinary) { + 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->parseKeyValues(path); + this->version = 0.1f; } } -void CmdSeq::parseBinary(const std::string& path) { - FileStream reader{path}; +void CmdSeq::parseBinary(const std::string& path_) { + FileStream reader{path_}; if (!reader) { return; } - auto version = reader.seek_in(31).read(); + reader.seek_in(31).read(this->version); auto sequenceCount = reader.read(); for (uint32_t s = 0; s < sequenceCount; s++) { @@ -65,8 +145,10 @@ void CmdSeq::parseBinary(const std::string& path) { } } -void CmdSeq::parseKeyValues(const std::string& path) { - KV1 cmdSeq{fs::readFileText(path)}; +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(); @@ -85,6 +167,41 @@ void CmdSeq::parseKeyValues(const std::string& path) { } } +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/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 index eb4de6124a1c38b07842fe8e99b14238287378b9..46e8ab51acb6628ecead2c7572cbd6a65b295e99 100644 GIT binary patch delta 323 zcmex=gz^6o#tq+DHuu|eGEd@=Ufgfbv{{-ffn{>N&4tbPSp^s;M+PZ<5h`~EF1OoCXmV(f*+d5$beAba;c*!YBLf2i E09x>I3jhEB delta 910 zcmex=gz^6o#tq+DCMQbVn&`l{`97-+6H8`JD#PUWEKh(u3C7LRTnQ{p1qzctu$%)5 z2ry2L7T~NuJ8*!Nfq`N3V*w3Dpc7vJT_nr6SwLh4*W`~Zw;}GEtROT1?qdczixG%H zKxOkA0T#x|8cKS=aJ>o(#!wc78=JLcVp7x6auV}WV~X=ji;`1|Q?lce^Ycnl^Gae; z@>61R6AOxql4C%^sTGO21v#nl87W12Ww~h#VB#VJC(x$VM-BNvHiB$_U~rLv9Y{|C zifx>2&d8`cdA{6}i4H7~Kq|14V+1QYO|kXe6&fxQ(^b diff --git a/test/res/toolpp/cmdseq/keyvalues.wc b/test/res/toolpp/cmdseq/keyvalues.wc index 8f4aa0496..eaf404d54 100644 --- a/test/res/toolpp/cmdseq/keyvalues.wc +++ b/test/res/toolpp/cmdseq/keyvalues.wc @@ -1,286 +1,279 @@ "Command Sequences" { - // Special commands (for special_cmd): - // 256 - Change Directory - // 257 - Copy File - // 258 - Delete File - // 259 - Rename File - // 261 - Copy File if it exists - // And they have no "run" string - "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" // Copy File - "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" // All game_exe things apparently have no wait, but it isn't used so whatever - } - } - "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" // Copy File - "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" // All game_exe things apparently have no wait, but it isn't used so whatever - } - } - "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" // Copy File - "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" // All game_exe things apparently have no wait, but it isn't used so whatever - } - } - "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" // Copy File - "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" // All game_exe things apparently have no wait, but it isn't used so whatever - } - } + "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/toolpp.cpp b/test/toolpp.cpp index a72a64b69..19ff0830c 100644 --- a/test/toolpp.cpp +++ b/test/toolpp.cpp @@ -1,7 +1,9 @@ #include +#include #include +using namespace sourcepp; using namespace toolpp; TEST(toolpp, cmdSeqOpenBinary) { @@ -14,6 +16,20 @@ TEST(toolpp, cmdSeqOpenKeyValues) { 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); From fd0d58d70cb36700a00855e4efce2efbc6b13fbc Mon Sep 17 00:00:00 2001 From: craftablescience Date: Tue, 27 Aug 2024 17:00:58 -0400 Subject: [PATCH 6/7] chore: update FUTURE.md --- FUTURE.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/FUTURE.md b/FUTURE.md index 3227de884..49f988de3 100644 --- a/FUTURE.md +++ b/FUTURE.md @@ -17,14 +17,11 @@ - 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` - - Add write support to KV1 `CmdSeq.wc` files when `kvpp` write support is implemented - Perhaps add the ability to parse TeamSpen's additions to the FGD format? - `vpkpp` - Cache file handles so they're not constantly getting closed/opened From d9897f743c77e61214f95d074fd4ddcbecb67cbd Mon Sep 17 00:00:00 2001 From: craftablescience Date: Tue, 27 Aug 2024 17:12:03 -0400 Subject: [PATCH 7/7] chore: missing spaces in readme table --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ecf574a6..e7970d830 100644 --- a/README.md +++ b/README.md @@ -109,8 +109,8 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one WC (CmdSeq) v0.1-0.2
Strata Source modifications - - ✅ + + ✅ ✅