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:
Marc
2022-10-10 21:01:16 +02:00
parent b8affcadbc
commit 1017d47312
5 changed files with 107 additions and 11 deletions
+1 -1
View File
@@ -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 "-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_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 # generate the compile_commands for vscode / clang
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
+13 -2
View File
@@ -5,6 +5,8 @@
#include <glib.h> #include <glib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
error_t getDataPath(int appid, char ** destination) { error_t getDataPath(int appid, char ** destination) {
GHashTable * gamePaths; GHashTable * gamePaths;
@@ -15,21 +17,30 @@ error_t getDataPath(int appid, char ** destination) {
int gameId = steam_gameIdFromAppId(appid); int gameId = steam_gameIdFromAppId(appid);
if(gameId < 0 ) { 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; return ERR_FAILURE;
} }
const char * path = g_hash_table_lookup(gamePaths, &appid);
char * gameFolder = g_build_filename(path, "steamapps/common", GAMES_NAMES[gameId], NULL); char * gameFolder = g_build_filename(path, "steamapps/common", GAMES_NAMES[gameId], NULL);
//the folder names for older an newer titles //the folder names for older an newer titles
char * dataFolderOld = g_build_filename(gameFolder, "Data Files", NULL); char * dataFolderOld = g_build_filename(gameFolder, "Data Files", NULL);
char * dataFolderNew = g_build_filename(gameFolder, "Data", NULL); char * dataFolderNew = g_build_filename(gameFolder, "Data", NULL);
g_free(gameFolder); g_free(gameFolder);
*destination = NULL; *destination = NULL;
//struct stat sb;
if(access(dataFolderOld, F_OK) == 0) { if(access(dataFolderOld, F_OK) == 0) {
*destination = strdup(dataFolderOld); *destination = strdup(dataFolderOld);
} else if(access(dataFolderNew, F_OK) == 0) { } else if(access(dataFolderNew, F_OK) == 0) {
*destination = strdup(dataFolderOld); *destination = strdup(dataFolderNew);
} }
g_free(dataFolderNew); g_free(dataFolderNew);
+26 -7
View File
@@ -3,6 +3,7 @@
#include "steam.h" #include "steam.h"
#include "file.h" #include "file.h"
#include <dirent.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
@@ -13,8 +14,6 @@
//TODO: deploy the game //TODO: deploy the game
error_t order_listPlugins(int appid, GList ** plugins) { error_t order_listPlugins(int appid, GList ** plugins) {
//save appid parsing //save appid parsing
//TODO: apply a similar mechanism everywhere //TODO: apply a similar mechanism everywhere
size_t appidStrLen = snprintf(NULL, 0, "%d", appid) + 1; 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 //esp && esm files are loadable
DIR * d = opendir(dataFolder); DIR * d = opendir(dataFolder);
struct dirent *dir; struct dirent *dir;
if (d) { if (d != NULL) {
while ((dir = readdir(d)) != NULL) { while ((dir = readdir(d)) != NULL) {
const char * extension = file_extractExtension(dir->d_name); 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) { if(strcmp(extension, "esp") == 0 || strcmp(extension, "esm") == 0) {
*plugins = g_list_append(*plugins, strdup(dir->d_name)); *plugins = g_list_append(*plugins, strdup(dir->d_name));
} }
} }
closedir(d);
} }
free(dataFolder); free(dataFolder);
return ERR_SUCCESS; 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) { error_t order_getLoadOrder(int appid, GList ** order) {
GHashTable * gamePaths; GHashTable * gamePaths;
@@ -66,11 +78,15 @@ error_t order_getLoadOrder(int appid, GList ** order) {
char appidStr[appidStrLen]; char appidStr[appidStrLen];
sprintf(appidStr, "%d", appid); 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);
//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; GList * l_currentLoadOrder = NULL;
if(access(loadOrderPath, F_OK)) { if(access(loadOrderPath, R_OK) == 0) {
FILE * f_loadOrder = fopen(loadOrderPath, "r"); FILE * f_loadOrder = fopen(loadOrderPath, "r");
size_t length = 0; size_t length = 0;
@@ -80,8 +96,11 @@ error_t order_getLoadOrder(int appid, GList ** order) {
if(line[0] == '#' || line[0] == '\n') if(line[0] == '#' || line[0] == '\n')
continue; continue;
removeCRLF_CR_LF(line);
l_currentLoadOrder = g_list_append(l_currentLoadOrder, strdup(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]; char appidStr[appidStrLen];
sprintf(appidStr, "%d", appid); 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); 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"); FILE * f_loadOrder = fopen(loadOrderPath, "w");
+66
View File
@@ -9,6 +9,7 @@
#include <libaudit.h> #include <libaudit.h>
#include "getDataPath.h" #include "getDataPath.h"
#include "loadOrder.h"
#include "overlayfs.h" #include "overlayfs.h"
#include "install.h" #include "install.h"
#include "getHome.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 --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 --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; return EXIT_FAILURE;
} }
@@ -543,6 +547,62 @@ static int swapMod(int argc, char ** argv) {
return order_swapPlace(appid, modIdA, modIdB); 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) { int main(int argc, char ** argv) {
if(argc < 2 ) return usage(); 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) else if(strcmp(argv[1], "--swap") == 0 || strcmp(argv[1], "-s") == 0)
returnValue = swapMod(argc, argv); 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) { else if(strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0) {
#ifdef __clang__ #ifdef __clang__
printf("%s: Clang: %d.%d.%d\n", VERSION, __clang_major__, __clang_minor__, __clang_patchlevel__); printf("%s: Clang: %d.%d.%d\n", VERSION, __clang_major__, __clang_minor__, __clang_patchlevel__);
+1 -1
View File
@@ -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. * 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 * @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); error_t steam_searchGames(GHashTable** tablePointer);