diff --git a/src/file.c b/src/file.c index e395b1b..b070169 100644 --- a/src/file.c +++ b/src/file.c @@ -128,3 +128,25 @@ void casefold(const char * folder) { closedir(d); } } + +const char * extractLastPart(const char * filePath, const char delimeter) { + const int length = strlen(filePath); + long index = -1; + for(long i= length - 1; i >= 0; i--) { + if(filePath[i] == delimeter) { + index = i + 1; + break; + } + } + + if(index <= 0 || index == length) return NULL; + return &filePath[index]; +} + +const char * extractExtension(const char * filePath) { + return extractLastPart(filePath, '.'); +} + +const char * extractFileName(const char * filePath) { + return extractLastPart(filePath, '/'); +} diff --git a/src/file.h b/src/file.h index 68c65bd..1f70f64 100644 --- a/src/file.h +++ b/src/file.h @@ -45,4 +45,21 @@ int move(const char * source, const char * destination); */ void casefold(const char * folder); + +const char * extractLastPart(const char * filePath, const char delimeter); + +/** + * @brief Return the extension of a file by looking for the character '.' + * @param filePath + * @return return a pointer to the address after the '.' or null if it was not found; + */ +const char * extractExtension(const char * filePath); + +/** + * @brief Return the file name by looking for the last character '/' + * @param filePath + * @return return a pointer to the address after the last '/' or null if it was not found (the path might not be a path in this case) + */ +const char * extractFileName(const char * filePath); + #endif diff --git a/src/install.c b/src/install.c index a381b76..a720943 100644 --- a/src/install.c +++ b/src/install.c @@ -7,28 +7,7 @@ #include "install.h" #include "main.h" #include "archives.h" - -static const char * extractLastPart(const char * filePath, const char delimeter) { - const int length = strlen(filePath); - long index = -1; - for(long i= length - 1; i >= 0; i--) { - if(filePath[i] == delimeter) { - index = i + 1; - break; - } - } - - if(index <= 0 || index == length) return NULL; - return &filePath[index]; -} - -static const char * extractExtension(const char * filePath) { - return extractLastPart(filePath, '.'); -} - -static const char * extractFileName(const char * filePath) { - return extractLastPart(filePath, '/'); -} +#include "file.h" error_t addMod(char * filePath, int appId) { error_t resultError = ERR_SUCCESS; diff --git a/src/loadOrder.c b/src/loadOrder.c new file mode 100644 index 0000000..2c812dc --- /dev/null +++ b/src/loadOrder.c @@ -0,0 +1,141 @@ +#include "loadOrder.h" +#include "main.h" +#include "steam.h" +#include "file.h" + +#include +#include + +error_t listPlugins(int appid, GList ** plugins) { + GHashTable * gamePaths; + error_t status = search_games(&gamePaths); + if(status == ERR_FAILURE) { + return ERR_FAILURE; + } + + int gameId = getGameIdFromAppId(appid); + if(gameId < 0 ) { + return ERR_FAILURE; + } + + //save appid parsing + //TODO: apply a similar mechanism everywhere + size_t appidStrLen = snprintf(NULL, 0, "%d", appid) + 1; + char appidStr[appidStrLen]; + sprintf(appidStr, "%d", appid); + + + + const char * path = g_hash_table_lookup(gamePaths, &appid); + char * steamGameFolder = g_build_filename(path, "steamapps/common", GAMES_NAMES[gameId], "Data", NULL); + + //esp && esm files are loadable + DIR * d = opendir(steamGameFolder); + struct dirent *dir; + if (d) { + while ((dir = readdir(d)) != NULL) { + const char * extension = extractExtension(dir->d_name); + if(strcmp(extension, "esp") == 0 || strcmp(extension, "esm") == 0) { + *plugins = g_list_append(*plugins, strdup(dir->d_name)); + } + } + } + + g_free(steamGameFolder); + return ERR_SUCCESS; +} + +error_t getLoadOrder(int appid, GList ** order) { + + GHashTable * gamePaths; + error_t status = search_games(&gamePaths); + if(status == ERR_FAILURE) { + return ERR_FAILURE; + } + + GList * l_plugins = NULL; + error_t error = listPlugins(appid, &l_plugins); + if(error == ERR_FAILURE) + return ERR_FAILURE; + + + int gameId = getGameIdFromAppId(appid); + if(gameId < 0 ) { + return ERR_FAILURE; + } + + size_t appidStrLen = snprintf(NULL, 0, "%d", appid) + 1; + 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); + + GList * l_currentLoadOrder = NULL; + if(access(loadOrderPath, F_OK)) { + FILE * f_loadOrder = fopen(loadOrderPath, "r"); + + size_t length = 0; + char * line = NULL; + + while(getline(&line, &length, f_loadOrder) > 0) { + if(line[0] == '#' || line[0] == '\n') + continue; + + l_currentLoadOrder = g_list_append(l_currentLoadOrder, strdup(line)); + } + } + + + GList * l_currentLoadOrderCursor = l_currentLoadOrder; + GList * l_completeLoadOrder = NULL; + + while(l_currentLoadOrderCursor != NULL) { + char * modName = l_currentLoadOrderCursor->data; + //TODO: finir sa + GList * mod = g_list_find_custom(l_plugins, modName, (GCompareFunc)strcmp); + if(mod == NULL) { + //The plugin is no longer installed + continue; + } else { + l_completeLoadOrder = g_list_append(l_completeLoadOrder, strdup(modName)); + } + l_currentLoadOrderCursor = g_list_next(l_currentLoadOrderCursor); + } + + *order = l_completeLoadOrder; + + g_list_free_full(l_plugins, free); + g_list_free_full(l_currentLoadOrder, free); + g_free(loadOrderPath); + return ERR_SUCCESS; +} + +error_t setLoadOrder(int appid, GList * loadOrder) { + GHashTable * gamePaths; + error_t status = search_games(&gamePaths); + if(status == ERR_FAILURE) { + return ERR_FAILURE; + } + + int gameId = getGameIdFromAppId(appid); + if(gameId < 0 ) { + return ERR_FAILURE; + } + + size_t appidStrLen = snprintf(NULL, 0, "%d", appid) + 1; + 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); + + FILE * f_loadOrder = fopen(loadOrderPath, "w"); + while(loadOrder != NULL) { + fwrite(loadOrder->data, sizeof(char), strlen(loadOrder->data), f_loadOrder); + loadOrder = g_list_next(loadOrder); + } + fclose(f_loadOrder); + + return ERR_SUCCESS; +} diff --git a/src/loadOrder.h b/src/loadOrder.h new file mode 100644 index 0000000..2b17a68 --- /dev/null +++ b/src/loadOrder.h @@ -0,0 +1,11 @@ +#ifndef __LOAD_ORDER_H__ +#define __LOAD_ORDER_H__ + +#include +#include "main.h" + +error_t listPlugins(int appid, GList ** list) __attribute__((warn_unused_result)); +error_t getLoadOrder(int appid, GList ** order) __attribute__((warn_unused_result)); +error_t setLoadOrder(int appid, GList * loadOrder) __attribute__((warn_unused_result)); + +#endif