diff --git a/CMakeLists.txt b/CMakeLists.txt index b45a38798..dac69a2c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,13 +26,15 @@ option(SOURCEPP_USE_VCRYPTPP "Build vcryptpp library" ${SOURC option(SOURCEPP_USE_VPKPP "Build vpkpp library" ${SOURCEPP_LIBS_START_ENABLED}) option(SOURCEPP_USE_VTFPP "Build vtfpp library" ${SOURCEPP_LIBS_START_ENABLED}) -option(SOURCEPP_BUILD_BENCHMARKS "Build benchmarks for supported libraries" OFF) -option(SOURCEPP_BUILD_C_WRAPPERS "Build C wrappers for supported libraries" OFF) -option(SOURCEPP_BUILD_WITH_OPENCL "Build with support for GPU compute" OFF) -option(SOURCEPP_BUILD_WITH_TBB "Build with support for std::execution" OFF) -option(SOURCEPP_BUILD_WITH_THREADS "Build with support for threading" ON) -option(SOURCEPP_BUILD_TESTS "Build tests for supported libraries" OFF) -option(SOURCEPP_BUILD_WIN7_COMPAT "Build with Windows 7 compatibility" OFF) +option(SOURCEPP_BUILD_BENCHMARKS "Build benchmarks for supported libraries" OFF) +option(SOURCEPP_BUILD_C_WRAPPERS "Build C wrappers for supported libraries" OFF) +option(SOURCEPP_BUILD_CSHARP_WRAPPERS "Build C# wrappers for supported libraries" OFF) +option(SOURCEPP_BUILD_PYTHON_WRAPPERS "Build Python wrappers for supported libraries" OFF) +option(SOURCEPP_BUILD_WITH_OPENCL "Build with support for GPU compute" OFF) +option(SOURCEPP_BUILD_WITH_TBB "Build with support for std::execution" OFF) +option(SOURCEPP_BUILD_WITH_THREADS "Build with support for threading" ON) +option(SOURCEPP_BUILD_TESTS "Build tests for supported libraries" OFF) +option(SOURCEPP_BUILD_WIN7_COMPAT "Build with Windows 7 compatibility" OFF) option(SOURCEPP_LINK_STATIC_MSVC_RUNTIME "Link to static MSVC runtime library" OFF) @@ -53,6 +55,9 @@ if(SOURCEPP_USE_VPKPP) set(SOURCEPP_USE_KVPP ON CACHE INTERNAL "" FORCE) endif() +if(SOURCEPP_BUILD_CSHARP_WRAPPERS) + set(SOURCEPP_BUILD_C_WRAPPERS ON CACHE INTERNAL "" FORCE) +endif() if(MSVC) # MSVC does not rely on tbb for std::execution policies, so we can force this on set(SOURCEPP_BUILD_WITH_TBB ON CACHE INTERNAL "" FORCE) @@ -73,6 +78,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(AddPrettyParser) include(AddSourcePPLibrary) +include(FetchContent) include(IncludeSubdirectory) include(PrintOptions) include(TargetOptimize) @@ -92,10 +98,24 @@ if(SOURCEPP_BUILD_C_WRAPPERS) endif() +# Python bindings, part 1 +if(SOURCEPP_BUILD_PYTHON_WRAPPERS) + set(SOURCEPP_PYTHON_NAME "${PROJECT_NAME}_python") + find_package(Python REQUIRED COMPONENTS Interpreter Development.Module) + FetchContent_Declare( + pybind11 + GIT_REPOSITORY "https://github.com/pybind/pybind11.git" + GIT_TAG "v2.13.6") + FetchContent_MakeAvailable(pybind11) + set(${SOURCEPP_PYTHON_NAME}_SOURCES "") + set(${SOURCEPP_PYTHON_NAME}_DEFINES "") + list(APPEND ${SOURCEPP_PYTHON_NAME}_DEPS pybind11::headers) +endif() + + # Tests, part 1 if(SOURCEPP_BUILD_TESTS) set(SOURCEPP_TEST_NAME "${PROJECT_NAME}_test") - include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY "https://github.com/google/googletest.git" @@ -138,16 +158,16 @@ endif() # Add libraries -add_sourcepp_library(bsppp NO_TEST ) # sourcepp::bsppp -add_sourcepp_library(dmxpp ) # sourcepp::dmxpp -add_sourcepp_library(gamepp ) # sourcepp::gamepp -add_sourcepp_library(kvpp BENCH) # sourcepp::kvpp -add_sourcepp_library(mdlpp ) # sourcepp::mdlpp -add_sourcepp_library(steampp C ) # sourcepp::steampp -add_sourcepp_library(toolpp ) # sourcepp::toolpp -add_sourcepp_library(vcryptpp C CSHARP ) # sourcepp::vcryptpp -add_sourcepp_library(vpkpp C CSHARP NO_TEST ) # sourcepp::vpkpp -add_sourcepp_library(vtfpp BENCH) # sourcepp::vtfpp +add_sourcepp_library(bsppp NO_TEST ) # sourcepp::bsppp +add_sourcepp_library(dmxpp ) # sourcepp::dmxpp +add_sourcepp_library(gamepp PYTHON ) # sourcepp::gamepp +add_sourcepp_library(kvpp BENCH) # sourcepp::kvpp +add_sourcepp_library(mdlpp ) # sourcepp::mdlpp +add_sourcepp_library(steampp C PYTHON ) # sourcepp::steampp +add_sourcepp_library(toolpp ) # sourcepp::toolpp +add_sourcepp_library(vcryptpp C CSHARP PYTHON ) # sourcepp::vcryptpp +add_sourcepp_library(vpkpp C CSHARP NO_TEST ) # sourcepp::vpkpp +add_sourcepp_library(vtfpp BENCH) # sourcepp::vtfpp # Tests, part 2 @@ -160,9 +180,18 @@ if(SOURCEPP_BUILD_TESTS) endif() +# Python bindings, part 2 +if(SOURCEPP_BUILD_PYTHON_WRAPPERS) + python_add_library(${SOURCEPP_PYTHON_NAME} MODULE "${CMAKE_CURRENT_SOURCE_DIR}/lang/python/src/sourcepp.cpp" ${${SOURCEPP_PYTHON_NAME}_SOURCES} WITH_SOABI) + set_target_properties(${SOURCEPP_PYTHON_NAME} PROPERTIES PREFIX "_" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lang/python/dist/sourcepp") + target_compile_definitions(${SOURCEPP_PYTHON_NAME} PRIVATE ${${SOURCEPP_PYTHON_NAME}_DEFINES}) + target_link_libraries(${SOURCEPP_PYTHON_NAME} PRIVATE ${${SOURCEPP_PYTHON_NAME}_DEPS}) +endif() + + # Print options print_options(OPTIONS USE_BSPPP USE_DMXPP USE_GAMEPP USE_KVPP USE_MDLPP USE_STEAMPP USE_TOOLPP USE_VCRYPTPP USE_VPKPP USE_VTFPP - BUILD_BENCHMARKS BUILD_C_WRAPPERS BUILD_WITH_OPENCL BUILD_WITH_TBB BUILD_WITH_THREADS BUILD_TESTS BUILD_WIN7_COMPAT + BUILD_BENCHMARKS BUILD_C_WRAPPERS BUILD_PYTHON_WRAPPERS BUILD_WITH_OPENCL BUILD_WITH_TBB BUILD_WITH_THREADS BUILD_TESTS BUILD_WIN7_COMPAT LINK_STATIC_MSVC_RUNTIME VPKPP_SUPPORT_VPK_V54) diff --git a/README.md b/README.md index de78d5c50..40722cef3 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Get Source engine instance window title/position/size ✅ ❌ - + Python @@ -84,7 +84,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Find Steam install folder ✅ - - C + C
Python @@ -119,7 +119,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one VICE encrypted files ✅ ✅ - C
C# + C
C#
Python diff --git a/cmake/AddSourcePPLibrary.cmake b/cmake/AddSourcePPLibrary.cmake index 18a760ed6..581dfd071 100644 --- a/cmake/AddSourcePPLibrary.cmake +++ b/cmake/AddSourcePPLibrary.cmake @@ -1,7 +1,9 @@ function(add_sourcepp_library TARGET) - cmake_parse_arguments(PARSE_ARGV 1 OPTIONS "C;CSHARP;NO_TEST;BENCH" "" "") + cmake_parse_arguments(PARSE_ARGV 1 OPTIONS "C;CSHARP;PYTHON;NO_TEST;BENCH" "" "") string(TOUPPER ${TARGET} TARGET_UPPER) if(SOURCEPP_USE_${TARGET_UPPER}) + set(PROPAGATE_VARS "") + # Add C++ include("${CMAKE_CURRENT_SOURCE_DIR}/src/${TARGET}/_${TARGET}.cmake") @@ -11,23 +13,31 @@ function(add_sourcepp_library TARGET) endif() # Add C# - if(OPTIONS_CSHARP) + if(SOURCEPP_BUILD_CSHARP_WRAPPERS AND OPTIONS_CSHARP) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/sourcepp/Buffer.cs.in" "${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/${TARGET}/Buffer.cs") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/sourcepp/String.cs.in" "${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/${TARGET}/String.cs") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/sourcepp/TARGET.csproj.in" "${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/${TARGET}/${TARGET}.csproj") + add_custom_target(${TARGET}_csharp DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lang/csharp/src/${TARGET}/${TARGET}.csproj") + add_dependencies(${TARGET}_csharp ${TARGET}c) endif() - set(PROPAGATE_VARS "") + # Add Python + if(SOURCEPP_BUILD_PYTHON_WRAPPERS AND OPTIONS_PYTHON) + list(APPEND ${SOURCEPP_PYTHON_NAME}_DEPS sourcepp::${TARGET}) + list(APPEND ${SOURCEPP_PYTHON_NAME}_DEFINES ${TARGET_UPPER}) + list(APPEND ${SOURCEPP_PYTHON_NAME}_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lang/python/src/${TARGET}.h") + list(APPEND PROPAGATE_VARS ${SOURCEPP_PYTHON_NAME}_DEPS ${SOURCEPP_PYTHON_NAME}_DEFINES ${SOURCEPP_PYTHON_NAME}_SOURCES) + endif() # Add tests - if(NOT OPTIONS_NO_TEST AND SOURCEPP_BUILD_TESTS) + if(SOURCEPP_BUILD_TESTS AND NOT OPTIONS_NO_TEST) list(APPEND ${SOURCEPP_TEST_NAME}_DEPS sourcepp::${TARGET}) list(APPEND ${SOURCEPP_TEST_NAME}_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/test/${TARGET}.cpp") list(APPEND PROPAGATE_VARS ${SOURCEPP_TEST_NAME}_DEPS ${SOURCEPP_TEST_NAME}_SOURCES) endif() # Add benchmarks - if(OPTIONS_BENCH AND SOURCEPP_BUILD_BENCHMARKS) + if(SOURCEPP_BUILD_BENCHMARKS AND OPTIONS_BENCH) add_executable(${TARGET}_bench "${CMAKE_CURRENT_SOURCE_DIR}/bench/${TARGET}.cpp") target_link_libraries(${TARGET}_bench PUBLIC ${SOURCEPP_BENCH_NAME} sourcepp::${TARGET}) include("${CMAKE_CURRENT_SOURCE_DIR}/bench/${TARGET}.cmake") diff --git a/docs/index.md b/docs/index.md index 8d4ff20e3..ef612a425 100644 --- a/docs/index.md +++ b/docs/index.md @@ -40,7 +40,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Get Source engine instance window title/position/size ✅ ❌ - + Python Run commands in a Source engine instance remotely @@ -76,7 +76,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one Find Steam install folder ✅ - - C + C
Python Find installed Steam games @@ -107,7 +107,7 @@ Several modern C++20 libraries for sanely parsing Valve formats, rolled into one VICE encrypted files ✅ ✅ - C
C# + C
C#
Python VFONT encrypted fonts diff --git a/ext/bufferstream b/ext/bufferstream index 689c50d56..72da37514 160000 --- a/ext/bufferstream +++ b/ext/bufferstream @@ -1 +1 @@ -Subproject commit 689c50d56a0eefb066209c281eac99599845edb6 +Subproject commit 72da375145d8d0cef590d9fe82e68c27f1d37481 diff --git a/ext/miniz b/ext/miniz index 1ff82be7d..35528ad76 160000 --- a/ext/miniz +++ b/ext/miniz @@ -1 +1 @@ -Subproject commit 1ff82be7d67f5c2f8b5497f538eea247861e0717 +Subproject commit 35528ad769143b9ed38a95a22d460b963e39f278 diff --git a/include/sourcepp/math/Integer.h b/include/sourcepp/math/Integer.h index d245fc014..7de6f416e 100644 --- a/include/sourcepp/math/Integer.h +++ b/include/sourcepp/math/Integer.h @@ -15,122 +15,10 @@ using std::uint16_t; using std::uint32_t; using std::uint64_t; -/// 3-byte wide unsigned integer -struct uint24_t { - uint24_t() = default; - - template - constexpr uint24_t(T value) // NOLINT(*-explicit-constructor) - : bytes{ - static_cast((value >> 16) & 0xff), - static_cast((value >> 8) & 0xff), - static_cast( value & 0xff), - } {} - - template - [[nodiscard]] constexpr operator T() const { // NOLINT(*-explicit-constructor) - return static_cast((bytes[0] << 16) | (bytes[1] << 8) | bytes[2]); - } - - template - constexpr uint24_t& operator=(T value) { - *this = {value}; - return *this; - } - - template - [[nodiscard]] constexpr uint24_t operator+(T value) const { - return {uint32_t{*this} + value}; - } - - template - constexpr void operator+=(T value) const { - *this = {uint32_t{*this} + value}; - } - - constexpr uint24_t operator++() { - return *this = {uint32_t{*this} + 1}; - } - - constexpr uint24_t operator++(int) { - uint24_t out{*this}; - *this = {uint32_t{*this} + 1}; - return out; - } - - template - [[nodiscard]] constexpr uint24_t operator-(T value) const { - return {uint32_t{*this} - value}; - } - - template - constexpr void operator-=(T value) const { - return *this = {uint32_t{*this} - value}; - } - - constexpr uint24_t operator--() { - return *this = {uint32_t{*this} - 1}; - } - - constexpr uint24_t operator--(int) { - uint24_t out{*this}; - *this = {uint32_t{*this} - 1}; - return out; - } - - template - [[nodiscard]] constexpr uint24_t operator*(T value) const { - return {uint32_t{*this} * value}; - } - - template - constexpr void operator*=(T value) const { - *this = {uint32_t{*this} * value}; - } - - template - [[nodiscard]] constexpr uint24_t operator/(T value) const { - return {uint32_t{*this} / value}; - } - - template - constexpr void operator/=(T value) const { - *this = {uint32_t{*this} / value}; - } - - template - [[nodiscard]] constexpr uint24_t operator%(T value) const { - return {uint32_t{*this} % value}; - } - - template - constexpr void operator%=(T value) const { - *this = {uint32_t{*this} % value}; - } - - template - [[nodiscard]] constexpr bool operator==(T value) const { - return uint32_t{*this} == value; - } - - template - [[nodiscard]] constexpr auto operator<=>(T value) const { - return uint32_t{*this} <=> value; - } - - [[nodiscard]] constexpr operator bool() const { // NOLINT(*-explicit-constructor) - return static_cast(uint32_t{*this}); - } - - uint8_t bytes[3]; -}; -static_assert(sizeof(uint24_t) == 3, "uint24_t is not 3 bytes wide!"); -static_assert(std::is_trivially_copyable_v, "uint24_t is not a POD type!"); - namespace sourcepp::math { template -concept Arithmetic = std::is_arithmetic_v || std::same_as; +concept Arithmetic = std::is_arithmetic_v; template [[nodiscard]] constexpr T remap(T value, T l1, T h1, T l2, T h2) { diff --git a/include/sourcepp/math/Vector.h b/include/sourcepp/math/Vector.h index b50ad76fd..d4395b81f 100644 --- a/include/sourcepp/math/Vector.h +++ b/include/sourcepp/math/Vector.h @@ -28,7 +28,7 @@ struct Vec { using value_type = P; - [[nodiscard]] consteval uint8_t size() const { + [[nodiscard]] constexpr uint8_t size() const { return S; } @@ -252,7 +252,6 @@ using Vec2i = Vec2i32; using Vec2ui8 = Vec2; using Vec2ui16 = Vec2; -using Vec2ui24 = Vec2; using Vec2ui32 = Vec2; using Vec2ui64 = Vec2; using Vec2ui = Vec2ui32; @@ -272,7 +271,6 @@ using Vec3i = Vec3i32; using Vec3ui8 = Vec3; using Vec3ui16 = Vec3; -using Vec3ui24 = Vec3; using Vec3ui32 = Vec3; using Vec3ui64 = Vec3; using Vec3ui = Vec3ui32; @@ -292,7 +290,6 @@ using Vec4i = Vec4i32; using Vec4ui8 = Vec4; using Vec4ui16 = Vec4; -using Vec4ui24 = Vec4; using Vec4ui32 = Vec4; using Vec4ui64 = Vec4; using Vec4ui = Vec4ui32; diff --git a/lang/python/.gitignore b/lang/python/.gitignore new file mode 100644 index 000000000..0c986d628 --- /dev/null +++ b/lang/python/.gitignore @@ -0,0 +1,4 @@ +# Build Files +__pycache__/ +dist/sourcepp/* +!dist/sourcepp/__init__.py diff --git a/lang/python/dist/sourcepp/__init__.py b/lang/python/dist/sourcepp/__init__.py new file mode 100644 index 000000000..d8f3097c9 --- /dev/null +++ b/lang/python/dist/sourcepp/__init__.py @@ -0,0 +1,5 @@ +from __future__ import annotations + +from ._sourcepp_python import __author__, __doc__, __version__, gamepp, sourcepp, steampp, vcryptpp + +__all__ = ['__author__', '__doc__', '__version__', 'gamepp', 'sourcepp', 'steampp', 'vcryptpp'] diff --git a/lang/python/src/gamepp.h b/lang/python/src/gamepp.h new file mode 100644 index 000000000..239e0804c --- /dev/null +++ b/lang/python/src/gamepp.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace py = pybind11; + +#include + +namespace gamepp { + +void register_python(py::module_& m) { + using namespace gamepp; + auto gamepp = m.def_submodule("gamepp"); + + py::class_(gamepp, "GameInstance") + .def_static("find", &GameInstance::find, py::arg("window_name_override") = "") + .def_property_readonly("window_title", &GameInstance::getWindowTitle) + .def_property_readonly("window_pos", &GameInstance::getWindowPos) + .def_property_readonly("window_size", &GameInstance::getWindowSize) + .def("command", &GameInstance::command) + .def("input_begin", &GameInstance::inputBegin) + .def("input_end", &GameInstance::inputEnd) + .def("input_once", &GameInstance::inputOnce) + .def("input_hold", &GameInstance::inputHold) + .def("wait", &GameInstance::wait); +} + +} // namespace gamepp diff --git a/lang/python/src/sourcepp.cpp b/lang/python/src/sourcepp.cpp new file mode 100644 index 000000000..353151646 --- /dev/null +++ b/lang/python/src/sourcepp.cpp @@ -0,0 +1,40 @@ +#include "sourcepp.h" + +#ifdef GAMEPP +#include "gamepp.h" +#endif + +#ifdef STEAMPP +#include "steampp.h" +#endif + +#ifdef VCRYPTPP +#include "vcryptpp.h" +#endif + +PYBIND11_MODULE(_sourcepp_python, m) { + m.doc() = "SourcePP: A Python wrapper around several modern C++20 libraries for sanely parsing Valve's formats."; + + m.attr("__author__") = "craftablescience"; + m.attr("__version__") = "dev"; + + sourcepp::register_python(m); + +#ifdef GAMEPP + gamepp::register_python(m); +#else + m.def_submodule("gamepp"); +#endif + +#ifdef STEAMPP + steampp::register_python(m); +#else + m.def_submodule("steampp"); +#endif + +#ifdef VCRYPTPP + vcryptpp::register_python(m); +#else + m.def_submodule("vcryptpp"); +#endif +} diff --git a/lang/python/src/sourcepp.h b/lang/python/src/sourcepp.h new file mode 100644 index 000000000..eeec1b764 --- /dev/null +++ b/lang/python/src/sourcepp.h @@ -0,0 +1,85 @@ +#pragma once + +#include + +#include +#include +#include + +namespace py = pybind11; + +#include + +namespace sourcepp { + +void register_python(py::module_& m) { + using namespace sourcepp; + auto sourcepp = m.def_submodule("sourcepp"); + + { + auto math = sourcepp.def_submodule("math"); + using namespace math; + + const auto registerVecType = [&math](std::string_view name) { + py::class_(math, name.data(), pybind11::buffer_protocol()) + .def_buffer([](V& v) -> py::buffer_info { + return {v.values.data(), static_cast(v.values.size())}; + }) + .def("__len__", &V::size) + .def("__setitem__", [](V& self, uint8_t index, V::value_type val) { self[index] = val; }) + .def("__getitem__", [](V& self, uint8_t index) { return self[index]; }) + .def_static("zero", &V::zero) + .def("is_zero", &V::isZero); + }; + + registerVecType.operator()("Vec2i8"); + registerVecType.operator()("Vec2i16"); + registerVecType.operator()("Vec2i32"); + registerVecType.operator()("Vec2i64"); + //registerVecType.operator()("Vec2i"); + + registerVecType.operator()("Vec2ui8"); + registerVecType.operator()("Vec2ui16"); + registerVecType.operator()("Vec2ui32"); + registerVecType.operator()("Vec2ui64"); + //registerVecType.operator()("Vec2ui"); + + registerVecType.operator()("Vec2f32"); + registerVecType.operator()("Vec2f64"); + //registerVecType.operator()("Vec2f"); + + registerVecType.operator()("Vec3i8"); + registerVecType.operator()("Vec3i16"); + registerVecType.operator()("Vec3i32"); + registerVecType.operator()("Vec3i64"); + //registerVecType.operator()("Vec3i"); + + registerVecType.operator()("Vec3ui8"); + registerVecType.operator()("Vec3ui16"); + registerVecType.operator()("Vec3ui32"); + registerVecType.operator()("Vec3ui64"); + //registerVecType.operator()("Vec3ui"); + + registerVecType.operator()("Vec3f32"); + registerVecType.operator()("Vec3f64"); + //registerVecType.operator()("Vec3f"); + + registerVecType.operator()("Vec4i8"); + registerVecType.operator()("Vec4i16"); + registerVecType.operator()("Vec4i32"); + registerVecType.operator()("Vec4i64"); + //registerVecType.operator()("Vec4i"); + + registerVecType.operator()("Vec4ui8"); + registerVecType.operator()("Vec4ui16"); + registerVecType.operator()("Vec4ui32"); + registerVecType.operator()("Vec4ui64"); + //registerVecType.operator()("Vec4ui"); + + registerVecType.operator()("Vec4f32"); + registerVecType.operator()("Vec4f64"); + //registerVecType.operator()("Vec4f"); + } +} + +} // namespace sourcepp diff --git a/lang/python/src/steampp.h b/lang/python/src/steampp.h new file mode 100644 index 000000000..24e1f8043 --- /dev/null +++ b/lang/python/src/steampp.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +namespace py = pybind11; + +#include + +namespace steampp { + +void register_python(py::module_& m) { + using namespace steampp; + auto steampp = m.def_submodule("steampp"); + + py::class_(steampp, "Steam") + .def(py::init<>()) + .def_property_readonly("install_dir", &Steam::getInstallDir) + .def_property_readonly("library_dirs", &Steam::getLibraryDirs) + .def_property_readonly("sourcemod_dir", &Steam::getSourceModDir) + .def_property_readonly("installed_apps", &Steam::getInstalledApps) + .def("is_app_installed", &Steam::isAppInstalled) + .def("get_app_name", &Steam::getAppName) + .def("get_app_install_dir", &Steam::getAppInstallDir) + .def("get_app_icon_path", &Steam::getAppIconPath) + .def("get_app_logo_path", &Steam::getAppLogoPath) + .def("get_app_box_art_path", &Steam::getAppBoxArtPath) + .def("get_app_store_art_path", &Steam::getAppStoreArtPath) + .def("is_app_using_source_engine", &Steam::isAppUsingSourceEngine) + .def("is_app_using_source_2_engine", &Steam::isAppUsingSource2Engine) + .def_property_readonly("valid", &Steam::operator bool); +} + +} // namespace steampp diff --git a/lang/python/src/vcryptpp.h b/lang/python/src/vcryptpp.h new file mode 100644 index 000000000..fc5fa33b7 --- /dev/null +++ b/lang/python/src/vcryptpp.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +namespace py = pybind11; + +#include + +namespace vcryptpp { + +void register_python(py::module_& m) { + using namespace vcryptpp; + auto vcryptpp = m.def_submodule("vcryptpp"); + + { + auto VFONT = vcryptpp.def_submodule("VFONT"); + using namespace VFONT; + + VFONT.attr("IDENTIFIER") = IDENTIFIER; + + VFONT.attr("MAGIC") = MAGIC; + + VFONT.def("decrypt_bytes", [](const py::bytes& data) -> py::bytes { + const std::string_view dataView{data}; + const auto d = decrypt({reinterpret_cast(dataView.data()), dataView.size()}); + return {reinterpret_cast(d.data()), d.size()}; + }, py::arg("data")); + } + + { + auto VICE = vcryptpp.def_submodule("VICE"); + using namespace VICE; + + { + auto KnownCodes = VICE.def_submodule("KnownCodes"); + using namespace KnownCodes; + + KnownCodes.attr("DEFAULT") = DEFAULT; + KnownCodes.attr("CONTAGION_WEAPONS") = CONTAGION_WEAPONS; + KnownCodes.attr("CONTAGION_SCRIPTS") = CONTAGION_SCRIPTS; + KnownCodes.attr("COUNTER_STRIKE_SOURCE") = COUNTER_STRIKE_SOURCE; + KnownCodes.attr("COUNTER_STRIKE_GLOBAL_OFFENSIVE") = COUNTER_STRIKE_GLOBAL_OFFENSIVE; + KnownCodes.attr("COUNTER_STRIKE_2") = COUNTER_STRIKE_2; + KnownCodes.attr("COUNTER_STRIKE_PROMOD") = COUNTER_STRIKE_PROMOD; + KnownCodes.attr("DAY_OF_DEFEAT_SOURCE") = DAY_OF_DEFEAT_SOURCE; + KnownCodes.attr("DYSTOPIA_1_2") = DYSTOPIA_1_2; + KnownCodes.attr("DYSTOPIA_1_3") = DYSTOPIA_1_3; + KnownCodes.attr("GOLDEN_EYE_SOURCE") = GOLDEN_EYE_SOURCE; + KnownCodes.attr("HALF_LIFE_2_CTF") = HALF_LIFE_2_CTF; + KnownCodes.attr("HALF_LIFE_2_DM") = HALF_LIFE_2_DM; + KnownCodes.attr("INSURGENCY") = INSURGENCY; + KnownCodes.attr("LEFT_4_DEAD_2") = LEFT_4_DEAD_2; + KnownCodes.attr("NO_MORE_ROOM_IN_HELL") = NO_MORE_ROOM_IN_HELL; + KnownCodes.attr("NUCLEAR_DAWN") = NUCLEAR_DAWN; + KnownCodes.attr("TACTICAL_INTERVENTION") = TACTICAL_INTERVENTION; + KnownCodes.attr("TEAM_FORTRESS_2") = TEAM_FORTRESS_2; + KnownCodes.attr("TEAM_FORTRESS_2_ITEMS") = TEAM_FORTRESS_2_ITEMS; + KnownCodes.attr("THE_SHIP") = THE_SHIP; + KnownCodes.attr("ZOMBIE_PANIC_SOURCE") = ZOMBIE_PANIC_SOURCE; + + KnownCodes.attr("EKV_GPU_DEFAULT") = EKV_GPU_DEFAULT; + KnownCodes.attr("EKV_GPU_ALIEN_SWARM") = EKV_GPU_ALIEN_SWARM; + KnownCodes.attr("EKV_GPU_LEFT_4_DEAD_1") = EKV_GPU_LEFT_4_DEAD_1; + KnownCodes.attr("EKV_GPU_LEFT_4_DEAD_2") = EKV_GPU_LEFT_4_DEAD_2; + KnownCodes.attr("EKV_GPU_PORTAL_2") = EKV_GPU_PORTAL_2; + } + + VICE.def("decrypt_bytes", [](const py::bytes& data, std::string_view code = KnownCodes::DEFAULT) -> py::bytes { + const std::string_view dataView{data}; + const auto d = decrypt({reinterpret_cast(dataView.data()), dataView.size()}, code); + return {reinterpret_cast(d.data()), d.size()}; + }, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT); + + VICE.def("decrypt_str", [](std::string_view data, std::string_view code = KnownCodes::DEFAULT) -> std::string { + const auto d = decrypt({reinterpret_cast(data.data()), data.size()}, code); + return {reinterpret_cast(d.data()), d.size()}; + }, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT); + + VICE.def("encrypt_bytes", [](const py::bytes& data, std::string_view code = KnownCodes::DEFAULT) -> py::bytes { + const std::string_view dataView{data}; + const auto e = encrypt({reinterpret_cast(dataView.data()), dataView.size()}, code); + return {reinterpret_cast(e.data()), e.size()}; + }, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT); + + VICE.def("encrypt_str", [](std::string_view data, std::string_view code = KnownCodes::DEFAULT) -> std::string { + const auto e = decrypt({reinterpret_cast(data.data()), data.size()}, code); + return {reinterpret_cast(e.data()), e.size()}; + }, py::arg("data"), py::arg("code") = KnownCodes::DEFAULT); + } +} + +} // namespace vcryptpp diff --git a/src/gamepp/gamepp.cpp b/src/gamepp/gamepp.cpp index b44892da9..d07b4aef5 100644 --- a/src/gamepp/gamepp.cpp +++ b/src/gamepp/gamepp.cpp @@ -13,7 +13,7 @@ using namespace sourcepp; #include std::optional GameInstance::find(std::string_view windowNameOverride) { - GameInstance instance; + GameInstance instance{}; if (!windowNameOverride.empty()) { instance.hwnd = FindWindowA(windowNameOverride.data(), nullptr); @@ -34,7 +34,7 @@ std::optional GameInstance::find(std::string_view windowNameOverri std::string GameInstance::getWindowTitle() const { // This should be large enough std::string title(512, '\0'); - if (auto size = GetWindowTextA(reinterpret_cast(this->hwnd), title.data(), title.length())) { + if (auto size = GetWindowTextA(reinterpret_cast(this->hwnd), title.data(), static_cast(title.length()))) { title.resize(size); return title; } diff --git a/src/toolpp/FGD.cpp b/src/toolpp/FGD.cpp index f9f955ca8..102692bfc 100644 --- a/src/toolpp/FGD.cpp +++ b/src/toolpp/FGD.cpp @@ -11,6 +11,7 @@ #include using namespace sourcepp; +using namespace std::string_view_literals; using namespace toolpp; namespace { @@ -467,11 +468,11 @@ void writeOptionalKeyValueStrings(BufferStream& writer, std::initializer_listwriter - .write("@include \"", 10) + .write("@include \""sv, false) .write(fgdPath, false) - .write("\"\n\n", 3); + .write("\"\n\n"sv, false); return *this; } FGDWriter& FGDWriter::version(int version) { this->writer - .write("@version(", 9) + .write("@version("sv, false) .write(std::to_string(version), false) - .write(")\n\n", 3); + .write(")\n\n"sv, false); return *this; } FGDWriter& FGDWriter::mapSize(math::Vec2i mapSize) { this->writer - .write("@mapsize(", 9) + .write("@mapsize("sv, false) .write(std::to_string(mapSize[0]), false) - .write(", ", 2) + .write(", "sv, false) .write(std::to_string(mapSize[1]), false) - .write(")\n\n", 3); + .write(")\n\n"sv, false); return *this; } FGDWriter& FGDWriter::materialExclusionDirs(const std::vector& dirs) { - this->writer.write("@MaterialExclusion\n[\n", 21); + this->writer.write("@MaterialExclusion\n[\n"sv, false); for (const auto& dir : dirs) { this->writer << '\t' << '\"'; this->writer.write(dir, false); this->writer << '\"' << '\n'; } - this->writer.write("]\n\n", 3); + this->writer.write("]\n\n"sv, false); return *this; } FGDWriter::AutoVisGroupWriter FGDWriter::beginAutoVisGroup(const std::string& parentName) { this->writer - .write("@AutoVisGroup = \"", 17) + .write("@AutoVisGroup = \""sv, false) .write(parentName, false) - .write("\"\n[\n", 4); + .write("\"\n[\n"sv, false); return AutoVisGroupWriter{*this}; } FGDWriter::AutoVisGroupWriter& FGDWriter::AutoVisGroupWriter::visGroup(const std::string& name, const std::vector& entities) { this->parent.writer - .write("\t\"", 2) + .write("\t\""sv, false) .write(name, false) - .write("\"\n\t[\n", 5); + .write("\"\n\t[\n"sv, false); for (const auto& entity : entities) { this->parent.writer - .write("\t\t\"", 3) + .write("\t\t\""sv, false) .write(entity, false) - .write("\"\n", 2); + .write("\"\n"sv, false); } - this->parent.writer.write("\t]\n", 3); + this->parent.writer.write("\t]\n"sv, false); return *this; } FGDWriter& FGDWriter::AutoVisGroupWriter::endAutoVisGroup() const { - this->parent.writer.write("]\n\n", 3); + this->parent.writer.write("]\n\n"sv, false); return this->parent; } @@ -684,20 +685,20 @@ FGDWriter::EntityWriter FGDWriter::beginEntity(const std::string& classType, con } } this->writer - .write("= ", 2) + .write("= "sv, false) .write(name, false) - .write(" :", 2); + .write(" :"sv, false); // Put the description on the same line if it's short if (description.size() < 32) { this->writer - .write(" \"", 2) + .write(" \""sv, false) .write(description, false); } else { this->writer - .write("\n\t\"", 3) + .write("\n\t\""sv, false) .write(description, false); } - this->writer.write("\"\n[\n", 4); + this->writer.write("\"\n[\n"sv, false); return EntityWriter{*this}; } @@ -709,10 +710,10 @@ FGDWriter::EntityWriter& FGDWriter::EntityWriter::keyValue(const std::string& na .write(valueType, false) .write(')'); if (readOnly) { - this->parent.writer.write(" readonly", 9); + this->parent.writer.write(" readonly"sv, false); } if (report) { - this->parent.writer.write(" report", 7); + this->parent.writer.write(" report"sv, false); } ::writeOptionalKeyValueStrings(this->parent.writer, {displayName, valueDefault, description}); this->parent.writer << '\n'; @@ -723,30 +724,30 @@ FGDWriter::EntityWriter::KeyValueChoicesWriter FGDWriter::EntityWriter::beginKey this->parent.writer .write('\t') .write(name, false) - .write("(choices)", 9); + .write("(choices)"sv, false); if (readOnly) { - this->parent.writer.write(" readonly", 9); + this->parent.writer.write(" readonly"sv, false); } if (report) { - this->parent.writer.write(" report", 7); + this->parent.writer.write(" report"sv, false); } ::writeOptionalKeyValueStrings(this->parent.writer, {displayName, valueDefault, description}); - this->parent.writer.write(" =\n\t[\n", 6); + this->parent.writer.write(" =\n\t[\n"sv, false); return KeyValueChoicesWriter{*this}; } FGDWriter::EntityWriter::KeyValueChoicesWriter& FGDWriter::EntityWriter::KeyValueChoicesWriter::choice(const std::string& value, const std::string& displayName) { this->parent.parent.writer - .write("\t\t\"", 3) + .write("\t\t\""sv, false) .write(value, false) - .write("\" : \"", 5) + .write("\" : \""sv, false) .write(displayName, false) - .write("\"\n", 2); + .write("\"\n"sv, false); return *this; } FGDWriter::EntityWriter& FGDWriter::EntityWriter::KeyValueChoicesWriter::endKeyValueChoices() const { - this->parent.parent.writer.write("\t]\n", 3); + this->parent.parent.writer.write("\t]\n"sv, false); return this->parent; } @@ -754,29 +755,29 @@ FGDWriter::EntityWriter::KeyValueFlagsWriter FGDWriter::EntityWriter::beginKeyVa this->parent.writer .write('\t') .write(name, false) - .write("(flags)", 7); + .write("(flags)"sv, false); if (readOnly) { - this->parent.writer.write(" readonly", 9); + this->parent.writer.write(" readonly"sv, false); } if (report) { - this->parent.writer.write(" report", 7); + this->parent.writer.write(" report"sv, false); } ::writeOptionalKeyValueStrings(this->parent.writer, {displayName, description}); - this->parent.writer.write(" =\n\t[\n", 6); + this->parent.writer.write(" =\n\t[\n"sv, false); return KeyValueFlagsWriter{*this}; } FGDWriter::EntityWriter::KeyValueFlagsWriter& FGDWriter::EntityWriter::KeyValueFlagsWriter::flag(uint64_t value, const std::string& displayName, bool enabledByDefault, const std::string& description) { this->parent.parent.writer - .write("\t\t", 2) + .write("\t\t"sv, false) .write(std::to_string(value), false) - .write(" : \"", 4) + .write(" : \""sv, false) .write(displayName, false) - .write("\" : ", 4) + .write("\" : "sv, false) .write(std::to_string(enabledByDefault), false); if (!description.empty()) { this->parent.parent.writer - .write(" : \"", 4) + .write(" : \""sv, false) .write(description, false) .write('\"'); } @@ -785,21 +786,21 @@ FGDWriter::EntityWriter::KeyValueFlagsWriter& FGDWriter::EntityWriter::KeyValueF } FGDWriter::EntityWriter& FGDWriter::EntityWriter::KeyValueFlagsWriter::endKeyValueFlags() const { - this->parent.parent.writer.write("\t]\n", 3); + this->parent.parent.writer.write("\t]\n"sv, false); return this->parent; } FGDWriter::EntityWriter& FGDWriter::EntityWriter::input(const std::string& name, const std::string& valueType, const std::string& description) { this->parent.writer .write('\t') - .write("input ", 6) + .write("input "sv, false) .write(name, false) .write('(') .write(valueType, false) .write(')'); if (!description.empty()) { this->parent.writer - .write(" : \"", 4) + .write(" : \""sv, false) .write(description, false) .write('\"'); } @@ -810,14 +811,14 @@ FGDWriter::EntityWriter& FGDWriter::EntityWriter::input(const std::string& name, FGDWriter::EntityWriter& FGDWriter::EntityWriter::output(const std::string& name, const std::string& valueType, const std::string& description) { this->parent.writer .write('\t') - .write("output ", 7) + .write("output "sv, false) .write(name, false) .write('(') .write(valueType, false) .write(')'); if (!description.empty()) { this->parent.writer - .write(" : \"", 4) + .write(" : \""sv, false) .write(description, false) .write('\"'); } @@ -826,7 +827,7 @@ FGDWriter::EntityWriter& FGDWriter::EntityWriter::output(const std::string& name } FGDWriter& FGDWriter::EntityWriter::endEntity() const { - this->parent.writer.write("]\n\n", 3); + this->parent.writer.write("]\n\n"sv, false); return this->parent; } diff --git a/src/vtfpp/VTF.cpp b/src/vtfpp/VTF.cpp index f7402f339..6d63c1880 100644 --- a/src/vtfpp/VTF.cpp +++ b/src/vtfpp/VTF.cpp @@ -1192,7 +1192,9 @@ std::vector VTF::bake() const { } writer - .write(0) // padding + .write(0) // padding + .write(0) // padding + .write(0) // padding .write(this->getResources().size() + hasAuxCompression) .write(0); // padding