diff --git a/cmake/steam_integration/CMakeLists.txt b/cmake/steam_integration/CMakeLists.txt index 1b9c9d948..f2b2f96c8 100644 --- a/cmake/steam_integration/CMakeLists.txt +++ b/cmake/steam_integration/CMakeLists.txt @@ -77,6 +77,8 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") +set_property(TARGET steam_integration PROPERTY CXX_STANDARD 17) + # Set the installation path to a local directory set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/bin") diff --git a/cmake/steam_integration/steam_integration.cpp b/cmake/steam_integration/steam_integration.cpp index 36d2f7606..23f9156af 100644 --- a/cmake/steam_integration/steam_integration.cpp +++ b/cmake/steam_integration/steam_integration.cpp @@ -1,10 +1,22 @@ #include "steam_integration.h" #if BUILD_STEAM +#include "steam_integration_callbacks.h" const int steam_app_id = 2660970; #include "steam_api.h" +steam_callback_queue_type steam_event_queue; + +class new_url_launch_parameters_t { +private: + STEAM_CALLBACK( new_url_launch_parameters_t, OnReceived, NewUrlLaunchParameters_t ); +}; + +void new_url_launch_parameters_t::OnReceived(NewUrlLaunchParameters_t* pCallback) { + steam_event_queue.push_back(steam_new_url_launch_parameters {}); +} + extern "C" { int steam_get_appid() { return steam_app_id; @@ -59,6 +71,14 @@ extern "C" { int steam_get_launch_command_line(char* buf, int bufsize) { return SteamApps()->GetLaunchCommandLine(buf, bufsize); } + + void* steam_run_callbacks() { + steam_event_queue.clear(); + + SteamAPI_RunCallbacks(); + + return &steam_event_queue; + } } #else // non-steam version @@ -101,6 +121,10 @@ extern "C" { int steam_get_launch_command_line(char*, int) { return 0; } + + void* steam_run_callbacks() { + return nullptr; + } } #endif diff --git a/cmake/steam_integration/steam_integration.h b/cmake/steam_integration/steam_integration.h index ba42b8ec2..8541723c4 100644 --- a/cmake/steam_integration/steam_integration.h +++ b/cmake/steam_integration/steam_integration.h @@ -26,6 +26,8 @@ extern "C" { DLL_EXPORT bool steam_set_rich_presence(const char*, const char*); DLL_EXPORT void steam_clear_rich_presence(); DLL_EXPORT int steam_get_launch_command_line(char* buf, int bufsize); + + DLL_EXPORT void* steam_run_callbacks(); } #undef DLL_EXPORT \ No newline at end of file diff --git a/cmake/steam_integration/steam_integration_callbacks.h b/cmake/steam_integration/steam_integration_callbacks.h new file mode 100644 index 000000000..6af8a1fd6 --- /dev/null +++ b/cmake/steam_integration/steam_integration_callbacks.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +struct steam_new_url_launch_parameters {}; + +using steam_callback_variant_type = std::variant< + steam_new_url_launch_parameters +>; + +using steam_callback_queue_type = std::vector< + steam_callback_variant_type +>; + + diff --git a/cmake/steam_integration/steam_integration_helpers.hpp b/cmake/steam_integration/steam_integration_helpers.hpp index 83f30e0a8..d73e9c1df 100644 --- a/cmake/steam_integration/steam_integration_helpers.hpp +++ b/cmake/steam_integration/steam_integration_helpers.hpp @@ -6,8 +6,9 @@ inline std::string steam_get_launch_command_line_string() { char buffer[512]; int num_bytes = steam_get_launch_command_line(buffer, sizeof(buffer)); - if (num_bytes != 0) { - return std::string(buffer, buffer + num_bytes); + if (num_bytes > 0 && uint32_t(num_bytes) < sizeof(buffer)) { + /* Exclude the terminating zero */ + return std::string(buffer, buffer + num_bytes - 1); } return std::string(); diff --git a/src/work.cpp b/src/work.cpp index 2a77ab90f..183778fd9 100644 --- a/src/work.cpp +++ b/src/work.cpp @@ -112,6 +112,7 @@ #include "augs/string/parse_url.h" #include "steam_integration.h" #include "steam_integration_helpers.hpp" +#include "steam_integration_callbacks.h" #include "work_result.h" @@ -2132,6 +2133,37 @@ work_result work(const int argc, const char* const * const argv) try { }); }; + auto process_steam_callbacks = [&]() { + if (const auto steam_queue = reinterpret_cast(steam_run_callbacks())) { + for (const auto steam_event : *steam_queue) { + std::visit( + [&](const E&) { + if constexpr(std::is_same_v) { + LOG("steam_new_url_launch_parameters received."); + + const auto steam_cli = steam_get_launch_command_line_string(); + + if (steam_cli.length() > 1) { + LOG("Detected Steam CLI (length: %x): %x", steam_cli.length(), steam_cli); + + config.client_start.set_custom(steam_cli); + + start_client_setup(); + } + else { + LOG("Invalid Steam CLI: %x", steam_cli); + } + } + else { + static_assert(always_false_v, "Non-exhaustive"); + } + }, + steam_event + ); + } + } + }; + auto do_imgui_pass = [&](const auto frame_num, auto& new_window_entropy, const auto& frame_delta, const bool in_direct_gameplay) { bool freeze_imgui_inputs = false; @@ -2895,7 +2927,7 @@ work_result work(const int argc, const char* const * const argv) try { const auto steam_cli = steam_get_launch_command_line_string(); - if (steam_cli.length() > 1) { + if (steam_cli.length() > 0) { LOG("Detected Steam CLI (length: %x): %x", steam_cli.length(), steam_cli); connect_to(steam_cli); } @@ -3214,6 +3246,7 @@ work_result work(const int argc, const char* const * const argv) try { const bool was_any_imgui_popup_opened = ImGui::IsPopupOpen(0u, ImGuiPopupFlags_AnyPopupId); do_imgui_pass(get_current_frame_num(), new_window_entropy, frame_delta, in_direct_gameplay); + process_steam_callbacks(); const auto viewing_config = get_setup_customized_config(); out.viewing_config = viewing_config;