From f8a584aef10a252460f2cd161826f44afdc3324b Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Wed, 29 Jun 2022 19:03:40 +0200 Subject: add source sdk path fetching, directly launch OF via sdk executable - guard Flatpak logic for non Linux UNIX systems - add /proc check on FreeBSD - allow arguments when launching OF - update README - add alternative launch options to CMakeLists.txt - add CFLAGS to all libraries and executables --- CMakeLists.txt | 13 ++++ README.md | 19 +++--- src/cli/CMakeLists.txt | 1 + src/cli/commands.c | 2 +- src/qt/CMakeLists.txt | 1 + src/qt/workers.cpp | 2 +- src/steam.c | 174 ++++++++++++++++++++++++++++++++++++++++++++----- src/steam.h | 33 +++++++--- 8 files changed, 208 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 139784b..82eaa1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,16 +14,29 @@ project(OFQT VERSION 0.1.3 LANGUAGES C) option(BUILD_CLI "Build the CLI client" OFF) option(BUILD_QT "Build the Qt GUI client" OFF) option(ENABLE_TESTS "Enable tests of the various components" OFF) +option(DIRECT_LAUNCH "Launch OpenFortress directly instead of via Steam" ON) +option(NAIVE_LAUNCH "Launch through the Steam Browser Protocol [Does not support Launch Options]" OFF) if (ENABLE_TESTS) enable_testing() endif() + set(TOAST_DEFAULT_REMOTE "http://toast.openfortress.fun/toast" CACHE STRING "Default Mirror to get OpenFortress files from") add_compile_definitions(NAME="${CMAKE_PROJECT_NAME}") add_compile_definitions(VERSION="${CMAKE_PROJECT_VERSION}") +if(DIRECT_LAUNCH) + message(STATUS "Launch type: Direct") + add_compile_definitions("STEAM_DIRECT_LAUNCH") +elseif(NAIVE_LAUNCH) + message(STATUS "Launch type: Steam Naive") + add_compile_definitions("STEAM_NAIVE_LAUNCH") +else() + message(STATUS "Launch type: Steam") +endif() + add_compile_definitions(TOAST_DEFAULT_REMOTE="${TOAST_DEFAULT_REMOTE}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") diff --git a/README.md b/README.md index 31aa2d0..608eb67 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,18 @@ # OFQT ## What is this? -OFQT is a library and a set of frontends for downloading OpenFortress. +OFQT is an OpenFortress Launcher -In its entirety OFQT is made up of: +### What is contained in the repository?? +The OFQT repo contains the following projects: - libtvn - a C library that deals revision information, downloading storing, applying, verifying, etc. - -- OFCL - a commandline client for libtvn - + a libary for dealing with TVN information +- libvdf + a VDF file parser - OFQT - a GUI for libtvn written in Qt - -and possibly more in the future + QT Frontend for libtvn +- OFCL + CLI Frontend for libtvn ## Supported Systems All Systems OpenFortress supports diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 38e5e13..2947a5b 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -12,6 +12,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) add_executable(${FRONTEND_NAME} ${CLI_SOURCES}) +target_compile_options(${FRONTEND_NAME} PUBLIC ${CFLAGS}) target_link_libraries(${FRONTEND_NAME} PRIVATE tvn) target_link_libraries(${FRONTEND_NAME} PRIVATE Threads::Threads) install(TARGETS ${FRONTEND_NAME}) diff --git a/src/cli/commands.c b/src/cli/commands.c index 4bac2f7..d206865 100644 --- a/src/cli/commands.c +++ b/src/cli/commands.c @@ -211,7 +211,7 @@ static int run(int c, char** v) goto run_cleanup; } - runOpenFortress(); + runOpenFortress(v+1, (size_t)(c-1)); run_cleanup: free(of_dir); diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 56d16c4..3702ad5 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -32,6 +32,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) add_executable(${FRONTEND_NAME} WIN32 ${QT_SOURCES}) +target_compile_options(${FRONTEND_NAME} PUBLIC ${CFLAGS}) target_link_libraries(${FRONTEND_NAME} PRIVATE tvn) target_link_libraries(${FRONTEND_NAME} PRIVATE Threads::Threads) target_link_libraries(${FRONTEND_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) diff --git a/src/qt/workers.cpp b/src/qt/workers.cpp index 8eb26df..41e8994 100644 --- a/src/qt/workers.cpp +++ b/src/qt/workers.cpp @@ -291,7 +291,7 @@ void Worker::doWork(const enum Worker::Tasks_t ¶meter) { case TASK_RUN: result = getSteamPID() > -1 ? RESULT_EXIT : RESULT_NO_STEAM; - if (result == RESULT_EXIT) runOpenFortress(); + if (result == RESULT_EXIT) runOpenFortress(NULL, 0); break; } diff --git a/src/steam.c b/src/steam.c index 4213768..83d05ce 100644 --- a/src/steam.c +++ b/src/steam.c @@ -5,6 +5,7 @@ #include #include +#include "vdf.h" #include "steam.h" #ifdef _WIN32 @@ -18,13 +19,18 @@ */ char* getSteamDir() { -#if defined(__linux__) +#if defined(__linux__) || defined(__FreeBSD__) char* home = getenv("HOME"); if (!home || !isDir(home)) return NULL; - size_t len = strlen(home) + strlen(FLATPAK_DIR); + size_t len = strlen(home); +#ifdef FLATPAK_DIR + len += strlen(FLATPAK_DIR); +#else + len += strlen(STEAM_DIR); +#endif char* path = malloc(len+1); strncpy(path, home, len); @@ -33,11 +39,13 @@ char* getSteamDir() if (isDir(path)) return path; +#ifdef FLATPAK_DIR strncpy(path, home, len); strncat(path, FLATPAK_DIR, len-strlen(path)); if (isDir(path)) return path; +#endif free(path); #elif defined(_WIN32) @@ -94,19 +102,85 @@ char* getOpenFortressDir() if (!sm_dir) return NULL; - sm_dir = realloc(sm_dir, strlen(sm_dir) + strlen(OPEN_FORTRESS_DIR) + 1); + sm_dir = realloc(sm_dir, strlen(sm_dir) + strlen(OS_PATH_SEP) + strlen(OPEN_FORTRESS_DIR) + 1); + strcat(sm_dir, OS_PATH_SEP); strcat(sm_dir, OPEN_FORTRESS_DIR); return sm_dir; } +char* getSourceSDK2013MpDir() +{ + char* librayfolders = getSteamDir(); + if (!librayfolders) + return NULL; + + librayfolders = realloc(librayfolders, strlen(librayfolders) + strlen(OS_PATH_SEP) + strlen(STEAMAPPS) + strlen(OS_PATH_SEP) + strlen(SOURCESDK_MANIFEST) + 1); + + strcat(librayfolders, OS_PATH_SEP); + strcat(librayfolders, STEAMAPPS); + strcat(librayfolders, OS_PATH_SEP); + strcat(librayfolders, LIBARYFOLDERS_VDF); + + struct vdf_object* o = vdf_parse_file(librayfolders); + free(librayfolders); + + char* sdkdir = NULL; + + if (o) + { + for (size_t i = 0; i < vdf_object_get_array_length(o); ++i) + { + struct vdf_object* library = vdf_object_index_array(o, i); + struct vdf_object* apps = vdf_object_index_array_str(library, "apps"); + + if (vdf_object_index_array_str(apps, SOURCESDK_APPID)) + { + struct vdf_object* path = vdf_object_index_array_str(library, "path"); + + size_t path_len = path->data.data_string.len + strlen(OS_PATH_SEP) + strlen(STEAMAPPS) + strlen(OS_PATH_SEP) + strlen(SOURCESDK_MANIFEST) + 1; + char* path_str = malloc(path_len); + + snprintf(path_str, path_len, "%s%s%s%s%s", vdf_object_get_string(path), OS_PATH_SEP, STEAMAPPS, OS_PATH_SEP, SOURCESDK_MANIFEST); + + struct vdf_object* k = vdf_parse_file(path_str); + free(path_str); + + if (k) + { + struct vdf_object* installdir = vdf_object_index_array_str(k, "installdir"); + + path_len = path->data.data_string.len + strlen(OS_PATH_SEP) + strlen(STEAMAPPS_COMMON) + strlen(OS_PATH_SEP) + installdir->data.data_string.len + 1; + path_str = malloc(path_len); + snprintf(path_str, path_len, "%s%s%s%s%s", vdf_object_get_string(path), OS_PATH_SEP, STEAMAPPS_COMMON, OS_PATH_SEP, vdf_object_get_string(installdir)); + + sdkdir = path_str; + + vdf_free_object(k); + } + } + } + + vdf_free_object(o); + } + + return sdkdir; +} + /** * function to fetch the PID of a running Steam process. * If none were found returns -1 */ long getSteamPID() { -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) + +#ifdef __FreeBSD__ + // on FreeBSD /proc is not mounted by default + if (!isDir("/proc")) + return -1; +#endif + long pid; char buf[PATH_MAX]; struct dirent* ent; @@ -157,22 +231,88 @@ long getSteamPID() #define STEAM_LAUNCH -int runOpenFortress() +int runOpenFortress(char** args, size_t arg_count) { -#ifdef STEAM_LAUNCH - #ifdef _WIN32 - return system("start steam://rungameid/11677091221058336806"); - #else - return system("xdg-open steam://rungameid/11677091221058336806"); - #endif +#ifdef STEAM_DIRECT_LAUNCH +#if defined(__linux__) || defined(__FreeBSD__) + // fork so we don't have to stay alive for the game + if (fork()) return 0; +#endif + + char* game = getSourceSDK2013MpDir(); + if (!game) + exit(0); -#else char* of_dir = getOpenFortressDir(); - char* steam = getSteamDir(); - steam = realloc(steam, strlen(steam) + strlen(OS_PATH_SEP) + strlen(STEAM_BIN) + 1); - strcat(steam, OS_PATH_SEP); - strcat(steam, STEAM_BIN); + if (!of_dir) + { + free(game); + exit(0); + } - return execl(steam, steam, "-applaunch", "243750", "-game", of_dir, "-secure", "-steam", NULL); + game = realloc(game, strlen(game) + strlen(OS_PATH_SEP) + strlen(HL2_EXE) + 1); + strcat(game, OS_PATH_SEP); + strcat(game, HL2_EXE); + +#if defined(__linux__) || defined(__FreeBSD__) + // we need to be in the steam environment to get the right locales + setenv("SteamEnv", "1", 1); +#endif + + char** argv = malloc(sizeof(char*) * (arg_count + 6)); + + size_t of_dir_len = strlen(of_dir); + of_dir = realloc(of_dir, of_dir_len + 3); + memmove(of_dir+1, of_dir, of_dir_len); + of_dir[0] = '"'; + of_dir[of_dir_len+1] = '"'; + + argv[0] = game; + argv[1] = "-game"; + argv[2] = of_dir; + argv[3] = "-secure"; + argv[4] = "-steam"; + for (size_t i = 0; i < arg_count; ++i) + argv[5+i] = args[i]; + argv[5+arg_count] = NULL; + + execv(game, argv); + + free(game); + free(of_dir); + + exit(0); + +#else + #ifdef STEAM_NAIVE_LAUNCH + #ifdef _WIN32 + return system("start steam://rungameid/11677091221058336806"); + #else + return system("xdg-open steam://rungameid/11677091221058336806"); + #endif + + #else + char* of_dir = getOpenFortressDir(); + char* steam = getSteamDir(); + steam = realloc(steam, strlen(steam) + strlen(OS_PATH_SEP) + strlen(STEAM_BIN) + 1); + strcat(steam, OS_PATH_SEP); + strcat(steam, STEAM_BIN); + + char** argv = malloc(sizeof(char*) * (arg_count + 8)); + + argv[0] = steam; + argv[1] = "-applaunch"; + argv[2] = "243750"; + argv[3] = "-game"; + argv[4] = of_dir; + argv[5] = "-secure"; + argv[6] = "-steam"; + for (size_t i = 0; i < arg_count; ++i) + argv[7+i] = args[i]; + argv[7+arg_count] = NULL; + + return execv(steam, argv); + #endif #endif } + \ No newline at end of file diff --git a/src/steam.h b/src/steam.h index 9c24337..c6f6887 100644 --- a/src/steam.h +++ b/src/steam.h @@ -14,31 +14,48 @@ extern "C" { #define STEAM_PROC "steam.exe" #define STEAM_BIN OS_PATH_SEP STEAM_PROC #else +// Works on Linux and FreeBSD #define STEAM_PROC "steam" #define STEAM_BIN "steam.sh" #endif -#define STEAM_APPID "243750" +#define LIBARYFOLDERS_VDF "libraryfolders.vdf" +#define SOURCESDK_APPID "243750" +#define SOURCESDK_MANIFEST "appmanifest_" SOURCESDK_APPID ".acf" -#ifdef _WIN32 -#define _STEAM_NAME "Steam" -#define STEAM_PGRM_64 "C:\\Program Files (x86)\\" _STEAM_NAME -#define STEAM_PGRM_86 "C:\\Program Files\\" _STEAM_NAME +#if defined(_WIN32) +#define HL2_EXE "hl2.exe" +#define STEAM_PGRM_64 "C:\\Program Files (x86)\\Steam" +#define STEAM_PGRM_86 "C:\\Program Files\\Steam" // TODO check if this is the right registry path for x86 #define REG_PATH "SOFTWARE\\Wow6432Node\\Valve\\Steam" -#else // _WIN32 + +#elif defined(__linux__) +#define HL2_EXE "hl2.sh" #define STEAM_DIR "/.local/share/Steam" #define FLATPAK_DIR "/.var/app/com.valvesoftware.Steam" STEAM_DIR + +#elif defined(__FreeBSD__) +#define HL2_EXE "hl2.sh" +#define STEAM_DIR "/.steam/steam" + #endif -#define SOURCEMOD_DIR "steamapps" OS_PATH_SEP "sourcemods" OS_PATH_SEP +#define STEAMAPPS "steamapps" +#define STEAMAPPS_COMMON STEAMAPPS OS_PATH_SEP "common" +#define SOURCEMOD_DIR STEAMAPPS OS_PATH_SEP "sourcemods" #define OPEN_FORTRESS_DIR "open_fortress" +#if defined(_WIN32) +#else +#endif + char* getSteamDir(); char* getSourcemodDir(); char* getOpenFortressDir(); +char* getSourceSDK2013MpDir(); long getSteamPID(); -int runOpenFortress(); +int runOpenFortress(char**, size_t); #ifdef __cplusplus } -- cgit v1.2.3