Allows to show the load order and list plugins.
i don't think allowing to edit the load order un the CLI will be easy. maybe it's doable with a TUI ? but if i continue to work with command line arguments it doesn't seem possible to do it cleanly. maybe i can do the same thing i did with the mod order. numbering mods and assking two numbers to swap. but this is shit. i only see 2 way this might go forward. 1. a gtk based ui like the one being developped in the interface branch but i doubt it will ever be finished if i don't intervene at some point. 2. a tui im really curious about tuis like nmtui or "n"(a node version manager).
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wmaybe-uninitialized")
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g -fsanitize=address -Werror -O0")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O2")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-g")
|
||||
|
||||
# generate the compile_commands for vscode / clang
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
|
||||
|
||||
+13
-2
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
||||
error_t getDataPath(int appid, char ** destination) {
|
||||
GHashTable * gamePaths;
|
||||
@@ -15,21 +17,30 @@ error_t getDataPath(int appid, char ** destination) {
|
||||
|
||||
int gameId = steam_gameIdFromAppId(appid);
|
||||
if(gameId < 0 ) {
|
||||
fprintf(stderr, "invalid appid");
|
||||
return ERR_FAILURE;
|
||||
}
|
||||
|
||||
const char * path = g_hash_table_lookup(gamePaths, &gameId);
|
||||
|
||||
if(path == NULL) {
|
||||
fprintf(stderr, "game not found\n");
|
||||
return ERR_FAILURE;
|
||||
}
|
||||
|
||||
const char * path = g_hash_table_lookup(gamePaths, &appid);
|
||||
char * gameFolder = g_build_filename(path, "steamapps/common", GAMES_NAMES[gameId], NULL);
|
||||
//the folder names for older an newer titles
|
||||
char * dataFolderOld = g_build_filename(gameFolder, "Data Files", NULL);
|
||||
char * dataFolderNew = g_build_filename(gameFolder, "Data", NULL);
|
||||
|
||||
g_free(gameFolder);
|
||||
|
||||
*destination = NULL;
|
||||
//struct stat sb;
|
||||
if(access(dataFolderOld, F_OK) == 0) {
|
||||
*destination = strdup(dataFolderOld);
|
||||
} else if(access(dataFolderNew, F_OK) == 0) {
|
||||
*destination = strdup(dataFolderOld);
|
||||
*destination = strdup(dataFolderNew);
|
||||
}
|
||||
|
||||
g_free(dataFolderNew);
|
||||
|
||||
+26
-7
@@ -3,6 +3,7 @@
|
||||
#include "steam.h"
|
||||
#include "file.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -13,8 +14,6 @@
|
||||
//TODO: deploy the game
|
||||
|
||||
error_t order_listPlugins(int appid, GList ** plugins) {
|
||||
|
||||
|
||||
//save appid parsing
|
||||
//TODO: apply a similar mechanism everywhere
|
||||
size_t appidStrLen = snprintf(NULL, 0, "%d", appid) + 1;
|
||||
@@ -30,19 +29,32 @@ error_t order_listPlugins(int appid, GList ** plugins) {
|
||||
//esp && esm files are loadable
|
||||
DIR * d = opendir(dataFolder);
|
||||
struct dirent *dir;
|
||||
if (d) {
|
||||
if (d != NULL) {
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
const char * extension = file_extractExtension(dir->d_name);
|
||||
//folder don't have file extensions
|
||||
if(extension == NULL)
|
||||
continue;
|
||||
|
||||
if(strcmp(extension, "esp") == 0 || strcmp(extension, "esm") == 0) {
|
||||
*plugins = g_list_append(*plugins, strdup(dir->d_name));
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
free(dataFolder);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static void removeCRLF_CR_LF(char * string) {
|
||||
int size = strlen(string);
|
||||
if(string[size - 1] == '\r') size--;
|
||||
if(string[size - 1] == '\n') size--;
|
||||
if(string[size - 1] == '\r') size--;
|
||||
string[size] = '\0';
|
||||
}
|
||||
|
||||
error_t order_getLoadOrder(int appid, GList ** order) {
|
||||
|
||||
GHashTable * gamePaths;
|
||||
@@ -66,11 +78,15 @@ error_t order_getLoadOrder(int appid, GList ** order) {
|
||||
char appidStr[appidStrLen];
|
||||
sprintf(appidStr, "%d", appid);
|
||||
|
||||
const char * path = g_hash_table_lookup(gamePaths, &appid);
|
||||
char * loadOrderPath = g_build_filename(path, "steamapps/compatdata", appidStr, "pfx/drive_c/users/steamuser/AppData/Local/", GAMES_NAMES[gameId], "loadorder.txt", NULL);
|
||||
const char * path = g_hash_table_lookup(gamePaths, &gameId);
|
||||
|
||||
|
||||
//this is the path i would use in windows but it seems it is not avaliable in all wine versions.
|
||||
//char * loadOrderPath = g_build_filename(path, "steamapps/compatdata", appidStr, "pfx/drive_c/users/steamuser/AppData/Local/", GAMES_NAMES[gameId], "loadorder.txt", NULL);
|
||||
char * loadOrderPath = g_build_filename(path, "steamapps/compatdata", appidStr, "pfx/drive_c/users/steamuser/Local Settings/Application Data/", GAMES_NAMES[gameId], "loadorder.txt", NULL);
|
||||
|
||||
GList * l_currentLoadOrder = NULL;
|
||||
if(access(loadOrderPath, F_OK)) {
|
||||
if(access(loadOrderPath, R_OK) == 0) {
|
||||
FILE * f_loadOrder = fopen(loadOrderPath, "r");
|
||||
|
||||
size_t length = 0;
|
||||
@@ -80,8 +96,11 @@ error_t order_getLoadOrder(int appid, GList ** order) {
|
||||
if(line[0] == '#' || line[0] == '\n')
|
||||
continue;
|
||||
|
||||
removeCRLF_CR_LF(line);
|
||||
|
||||
l_currentLoadOrder = g_list_append(l_currentLoadOrder, strdup(line));
|
||||
}
|
||||
if(line != NULL)free(line);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +144,7 @@ error_t order_setLoadOrder(int appid, GList * loadOrder) {
|
||||
char appidStr[appidStrLen];
|
||||
sprintf(appidStr, "%d", appid);
|
||||
|
||||
const char * path = g_hash_table_lookup(gamePaths, &appid);
|
||||
const char * path = g_hash_table_lookup(gamePaths, &gameId);
|
||||
char * loadOrderPath = g_build_filename(path, "steamapps/compatdata", appidStr, "pfx/drive_c/users/steamuser/AppData/Local/", GAMES_NAMES[gameId], "loadorder.txt", NULL);
|
||||
|
||||
FILE * f_loadOrder = fopen(loadOrderPath, "w");
|
||||
|
||||
+66
@@ -9,6 +9,7 @@
|
||||
#include <libaudit.h>
|
||||
|
||||
#include "getDataPath.h"
|
||||
#include "loadOrder.h"
|
||||
#include "overlayfs.h"
|
||||
#include "install.h"
|
||||
#include "getHome.h"
|
||||
@@ -60,6 +61,9 @@ static int usage() {
|
||||
printf("Use --swap <APPID> <MODID A> MODID B> to swap two mod in the loading order\n");
|
||||
|
||||
printf("Use --version or -v to get the version number\n");
|
||||
|
||||
printf("Use --show-load-order <APPID>\n");
|
||||
printf("Use --list-plugins <APPID>\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -543,6 +547,62 @@ static int swapMod(int argc, char ** argv) {
|
||||
return order_swapPlace(appid, modIdA, modIdB);
|
||||
}
|
||||
|
||||
static int printLoadOrder(int argc, char ** argv) {
|
||||
if(argc != 3) return usage();
|
||||
|
||||
char * appIdStr = argv[2];
|
||||
int appid = validateAppId(appIdStr);
|
||||
if(appid < 0) {
|
||||
fprintf(stderr, "Invalid appid");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
GList * order = NULL;
|
||||
error_t status = order_getLoadOrder(appid, &order);
|
||||
if(status != ERR_SUCCESS) {
|
||||
fprintf(stderr, "Could not fetch the load order\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("If the load order is empty that mean it wasn't set\n");
|
||||
|
||||
GList * cur_order = order;
|
||||
while (cur_order != NULL) {
|
||||
printf("%s\n", (char *)cur_order->data);
|
||||
cur_order = g_list_next(cur_order);
|
||||
}
|
||||
|
||||
g_list_free_full(order, free);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int printPlugins(int argc, char ** argv) {
|
||||
if(argc != 3) return usage();
|
||||
|
||||
char * appIdStr = argv[2];
|
||||
int appid = validateAppId(appIdStr);
|
||||
if(appid < 0) {
|
||||
fprintf(stderr, "Invalid appid");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
GList * mods = NULL;
|
||||
error_t status = order_listPlugins(appid, &mods);
|
||||
if(status != ERR_SUCCESS) {
|
||||
fprintf(stderr, "Could not list plugins\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
GList * cur_mods = mods;
|
||||
while (cur_mods != NULL) {
|
||||
printf("%s\n", (char *)cur_mods->data);
|
||||
cur_mods = g_list_next(cur_mods);
|
||||
}
|
||||
|
||||
g_list_free_full(mods, free);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
if(argc < 2 ) return usage();
|
||||
|
||||
@@ -608,6 +668,12 @@ int main(int argc, char ** argv) {
|
||||
else if(strcmp(argv[1], "--swap") == 0 || strcmp(argv[1], "-s") == 0)
|
||||
returnValue = swapMod(argc, argv);
|
||||
|
||||
else if(strcmp(argv[1], "--list-plugins") == 0)
|
||||
returnValue = printPlugins(argc, argv);
|
||||
|
||||
else if(strcmp(argv[1], "--show-load-order") == 0)
|
||||
returnValue = printLoadOrder(argc, argv);
|
||||
|
||||
else if(strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0) {
|
||||
#ifdef __clang__
|
||||
printf("%s: Clang: %d.%d.%d\n", VERSION, __clang_major__, __clang_minor__, __clang_patchlevel__);
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ _Static_assert(LEN(GAMES_APPIDS) == LEN(GAMES_NAMES), "Game APPIDS and Game Name
|
||||
* This method has a singleton so after the first execution it will no rescan for new games.
|
||||
*
|
||||
* @param status pointer to a status variable that will be modified to EXIT_SUCCESS or EXIT_FAILURE
|
||||
* @return GHashTable* a map appid(int) => path(char *) to the corresponding steam library
|
||||
* @return GHashTable* a map gameId(int) => path(char *) to the corresponding steam library
|
||||
*/
|
||||
error_t steam_searchGames(GHashTable** tablePointer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user