From a324ef51c9b1aaeaf83ee8d0ff28529c4f37ac4e Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Fri, 2 Feb 2024 00:54:40 +0200 Subject: [PATCH] menu: fix players model menu --- src/client/menu/menu.c | 147 +++++++++++++++++++++++++++++++++++----- src/common/filesystem.c | 13 ++-- 2 files changed, 138 insertions(+), 22 deletions(-) diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index e748ace3..9f171785 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -5494,9 +5494,9 @@ PlayerDirectoryList(void) { char* findname = "players/*"; char** list = 0; - int num = 0; + int num = 0, dirnum = 0; - /* get a list of "players" subdirectories */ + /* get a list of "players" subdirectories or files */ if ((list = FS_ListFiles2(findname, &num, 0, 0)) == NULL) { return false; @@ -5512,10 +5512,12 @@ PlayerDirectoryList(void) YQ2_COM_CHECK_OOM(data, "calloc()", num * sizeof(char*)) s_directory.data = data; - s_directory.num = num; for (int i = 0; i < num; ++i) { + char dirname[MAX_QPATH], *dirsize; + int dirnamelen = 0, j; + // last element of FS_FileList maybe null if (list[i] == 0) { @@ -5524,15 +5526,40 @@ PlayerDirectoryList(void) ReplaceCharacters(list[i], '\\', '/'); - char* s = (char*)malloc(MAX_QPATH); - char* t = list[i]; + dirsize = strchr(list[i] + strlen(findname), '/'); + if (dirsize) + { + dirnamelen = dirsize - list[i]; + memcpy(dirname, list[i], dirnamelen); + dirname[dirnamelen] = 0; + } + else + { + strcpy(dirname, list[i]); + } - YQ2_COM_CHECK_OOM(s, "malloc()", MAX_QPATH * sizeof(char)) + for (j = 0; j < dirnum; j++) + { + if (!strcmp(dirname, data[j])) + { + break; + } + } - Q_strlcpy(s, t, MAX_QPATH); - data[i] = s; + if (j == dirnum) + { + char* s = (char*)malloc(MAX_QPATH); + + YQ2_COM_CHECK_OOM(s, "malloc()", MAX_QPATH * sizeof(char)) + + Q_strlcpy(s, dirname, MAX_QPATH); + data[dirnum] = s; + dirnum ++; + } } + s_directory.num = dirnum; + // free file list FS_FreeList(list, num); @@ -5554,6 +5581,94 @@ HasSkinInDir(const char *dirname, const char *ext, int *num) return FS_ListFiles2(findname, num, 0, 0); } +static char** +HasSkinsInDir(const char *dirname, int *num) +{ + char **list_png, **list_pcx, **list_m8; + char **curr = NULL, **list = NULL; + int num_png, num_pcx, num_m8; + + *num = 0; + + list_png = HasSkinInDir(dirname, "png", &num_png); + if (list_png) + { + *num += num_png - 1; + } + + list_pcx = HasSkinInDir(dirname, "pcx", &num_pcx); + if (list_pcx) + { + *num += num_pcx - 1; + } + + list_m8 = HasSkinInDir(dirname, "m8", &num_m8); + if (list_m8) + { + *num += num_m8 - 1; + } + + if (num) + { + curr = list = malloc(sizeof(char *) * (*num + 1)); + YQ2_COM_CHECK_OOM(list, "realloc()", (size_t)sizeof(char *) * (*num + 1)) + + if (list_png) + { + int j; + + for (j = 0; j < num_png; j ++) + { + if (list_png[j]) + { + *curr = list_png[j]; + curr++; + } + } + + free(list_png); + } + + if (list_pcx) + { + int j; + + for (j = 0; j < num_pcx; j ++) + { + if (list_pcx[j]) + { + *curr = list_pcx[j]; + curr++; + } + } + + free(list_pcx); + } + + if (list_m8) + { + int j; + + for (j = 0; j < num_m8; j ++) + { + if (list_m8[j]) + { + *curr = list_m8[j]; + curr++; + } + } + + free(list_m8); + } + + *curr = NULL; + curr++; + *num = curr - list; + } + + return list; +} + /* * list all valid player models. @@ -5586,15 +5701,6 @@ PlayerModelList(void) continue; } - /* get a list of pcx files */ - if ( - (list = HasSkinInDir(s_directory.data[i], "png", &num)) == NULL && - (list = HasSkinInDir(s_directory.data[i], "pcx", &num)) == NULL && - (list = HasSkinInDir(s_directory.data[i], "m8", &num)) == NULL) - { - continue; - } - /* contains triangle .md2 model */ s = s_directory.data[i]; @@ -5608,6 +5714,13 @@ PlayerModelList(void) continue; } + list = HasSkinsInDir(s_directory.data[i], &num); + /* get a list of pcx files */ + if (!num || !list) + { + continue; + } + /* count valid skins, which consist of a skin with a matching "_i" icon */ s_skinnames[mdl].num = 0; diff --git a/src/common/filesystem.c b/src/common/filesystem.c index f0d8e67b..ed8989e5 100644 --- a/src/common/filesystem.c +++ b/src/common/filesystem.c @@ -98,9 +98,9 @@ typedef struct } fsPackTypes_t; fsHandle_t fs_handles[MAX_HANDLES]; -fsLink_t *fs_links; -fsSearchPath_t *fs_searchPaths; -fsSearchPath_t *fs_baseSearchPaths; +fsLink_t *fs_links = NULL; +fsSearchPath_t *fs_searchPaths = NULL; +fsSearchPath_t *fs_baseSearchPaths = NULL; /* Pack formats / suffixes. */ fsPackTypes_t fs_packtypes[] = { @@ -422,7 +422,10 @@ FS_FOpenFile(const char *rawname, fileHandle_t *f, qboolean gamedir_only) // TODO: A flag to ignore paks would be better if ((strcmp(fs_gamedirvar->string, "") == 0) && search->pack) { if ((strcmp(name, "maps.lst") == 0) || (strncmp(name, "players/", 8) == 0)) { - continue; + if (FS_FileInGamedir(name)) + { + continue; + } } } @@ -877,7 +880,7 @@ FS_LoadPK3(const char *packPath) if (unzGetGlobalInfo(handle, &global) != UNZ_OK) { unzClose(handle); - Com_Error(ERR_FATAL, "FS_LoadPK3: '%s' is not a pack file", packPath); + Com_Error(ERR_FATAL, "%s: '%s' is not a pack file", __func__, packPath); } numFiles = global.number_entry;