Rework maplist command so mod maps are displayed last instead of first (so nearer the input line instead of the order the engine searches them).

Also .bsp vs .bsp.gz etc maps are now ordered consistently too.
Modifiers like maps/foo#bar.ent are now shown separately in the listing too.
Hide maps that are shadowed by a higher-priority gamedir (so no dupes).
Closes https://github.com/fte-team/fteqw/issues/171
This commit is contained in:
Shpoike 2023-04-23 05:47:27 +01:00
parent 6b69fe0378
commit ff80b3bd59
2 changed files with 86 additions and 15 deletions

View File

@ -3472,12 +3472,46 @@ void COM_EnumerateFiles (const char *match, int (QDECL *func)(const char *, qofs
for (search = com_searchpaths; search ; search = search->next)
{
// is the element a pak file?
if (!search->handle->EnumerateFiles(search->handle, match, func, parm))
break;
}
}
//scan packages in a reverse order, ie lowest priority first (for less scrolling upwards)
void COM_EnumerateFilesReverse (const char *match, int (QDECL *func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t*), void *parm)
{
searchpath_t *search;
searchpath_t **rev;
size_t count;
if (!strncmp(match, "file:", 5))
{
if (fs_allowfileuri)
{
char syspath[MAX_OSPATH];
struct fs_enumerate_fileuri_s e;
e.func = func;
e.parm = parm;
if (Sys_ResolveFileURL(match, strlen(match), syspath, sizeof(syspath)))
Sys_EnumerateFiles(NULL, syspath, COM_EnumerateFiles_FileURI, &e, NULL);
}
return;
}
for (search = com_searchpaths, count=0; search ; search = search->next)
count++;
rev = BZ_Malloc(sizeof(*rev)*count);
for (search = com_searchpaths, count=0; search ; search = search->next)
rev[count++] = search;
while(count)
{
search = rev[--count];
if (!search->handle->EnumerateFiles(search->handle, match, func, parm))
break;
}
BZ_Free(rev);
}
void COM_FlushTempoaryPacks(void) //flush all temporary packages
{
searchpath_t *sp, **link;

View File

@ -403,6 +403,7 @@ static void SV_redundantcommand_f(void)
static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
{
searchpathfuncs_t **oldspath = parm;
const char *levelshots[] =
{
"levelshots/%s.tga",
@ -415,10 +416,53 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
size_t u;
char stripped[MAX_QPATH];
char completed[256];
char *ext = parm;
const char *cmd = name+5; //the arg to pass to `map`
const char *ext;
flocation_t loc;
if (name[5] == 'b' && name[6] == '_') //skip box models
return true;
if (FS_FLocateFile(name, FSLF_IFFOUND, &loc))
{
if (loc.search->handle != spath)
return true; //shadowed
}
else
return true; //wtf?
ext = COM_GetFileExtension (name+5, NULL);
if (!strcmp(ext, ".gz") || !strcmp(ext, ".xz"))
ext = COM_GetFileExtension (name+5, ext); //.gz files should be listed too.
if (!strcmp(ext, ".bsp"))
{
ext = ""; //hide it
cmd = stripped; //omit it, might as well. should give less confusing mapname serverinfo etc.
}
else if (!Q_strcasecmp(ext, ".bsp") || !Q_strcasecmp(ext, ".bsp.gz") || !Q_strcasecmp(ext, ".bsp.xz"))
;
#ifdef TERRAIN
else if (!Q_strcasecmp(ext, ".map") || !Q_strcasecmp(ext, ".map.gz") || !Q_strcasecmp(ext, ".hmp"))
;
#endif
#ifdef MAP_PROC
else if (!Q_strcasecmp(ext, ".cm"))
;
#endif
else if (!Q_strcasecmp(ext, ".ent") && strchr(name+5, '#'))
{ //FIXME hide if earlier that the .bsp
ext = ""; //hide it.
cmd = stripped; //do NOT use the .ent extension here
}
else
return true; //probably a .lit
if (*oldspath != spath)
{
*oldspath = spath;
Con_Printf(S_COLOR_GRAY"From %s\n", loc.search->purepath);
}
*completed = 0;
#ifdef HAVE_CLIENT
{
@ -433,31 +477,24 @@ static int QDECL ShowMapList (const char *name, qofs_t flags, time_t mtime, void
}
#endif
name += 5; //skip the maps/ prefix
COM_StripExtension(name, stripped, sizeof(stripped));
COM_StripExtension(name+5, stripped, sizeof(stripped));
for (u = 0; u < countof(levelshots); u++)
{
const char *ls = va(levelshots[u], stripped);
if (COM_FCheckExists(ls))
{
Con_Printf("^[\\map\\%s\\img\\%s\\w\\64\\h\\48^]", name, ls);
Con_Printf("^[[%s%s]%s\\map\\%s\\tipimg\\%s^]\n", stripped, ext, completed, name, ls);
Con_Printf("^[\\map\\%s\\img\\%s\\w\\64\\h\\48^]", cmd, ls);
Con_Printf("^[[%s%s]%s\\map\\%s\\tipimg\\%s\\tip\\from %s/%s^]\n", stripped, ext, completed, cmd, ls, loc.search->logicalpath, name);
return true;
}
}
Con_Printf("^[[%s%s]%s\\map\\%s^]\n", stripped, ext, completed, name);
Con_Printf("^[[%s%s]%s\\map\\%s\\tip\\from %s/%s^]\n", stripped, ext, completed, cmd, loc.search->logicalpath, name);
return true;
}
static void SV_MapList_f(void)
{
//FIXME: maps/mapname#modifier.ent
COM_EnumerateFiles("maps/*.bsp", ShowMapList, "");
COM_EnumerateFiles("maps/*.bsp.gz", ShowMapList, ".bsp.gz");
COM_EnumerateFiles("maps/*.bsp.xz", ShowMapList, ".bsp.xz");
COM_EnumerateFiles("maps/*.map", ShowMapList, ".map");
COM_EnumerateFiles("maps/*.map.gz", ShowMapList, ".gz");
COM_EnumerateFiles("maps/*.cm", ShowMapList, ".cm");
COM_EnumerateFiles("maps/*.hmp", ShowMapList, ".hmp");
searchpathfuncs_t *spath = NULL;
COM_EnumerateFilesReverse("maps/*.*", ShowMapList, &spath);
}
static int QDECL CompleteMapList (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)