Allow search_begin to filter by package names.

This commit is contained in:
Shpoike 2020-09-04 13:17:28 +01:00
parent 8915c41e0c
commit f232be4f77
3 changed files with 62 additions and 39 deletions

View File

@ -2516,9 +2516,11 @@ static void COM_ListFiles(void *ctx, searchpath_t *spath, const char *pattern, q
} }
#endif #endif
} }
void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath)) void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath), unsigned int flags, const char *pkgfilter)
{ {
searchpath_t *search; searchpath_t *search;
const char *sp;
qboolean foundpackage = false;
if (*pattern == '/' || strchr(pattern, ':') //block absolute paths if (*pattern == '/' || strchr(pattern, ':') //block absolute paths
|| strchr(pattern, '\\') //block unportable paths (also ones that mess up other checks) || strchr(pattern, '\\') //block unportable paths (also ones that mess up other checks)
@ -2531,6 +2533,23 @@ void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx,
//don't add the same pak twice. //don't add the same pak twice.
for (search = com_searchpaths; search; search = search->next) for (search = com_searchpaths; search; search = search->next)
{ {
if (pkgfilter)
{
if (flags & (1u<<1))
sp = search->purename;
else
{
sp = strchr(search->purename, '/');
if (sp && !strchr(++sp, '/'))
;
else
continue; //ignore packages inside other packages. they're just too weird.
}
if (strcmp(pkgfilter, sp))
continue; //ignore this package
}
foundpackage = true;
if (search->pack) if (search->pack)
{ {
pack_t *pak = search->pack; pack_t *pak = search->pack;
@ -2546,9 +2565,16 @@ void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx,
COM_ListFiles(ctx, search, pattern, cb); COM_ListFiles(ctx, search, pattern, cb);
} }
} }
if (flags & (1u<<1) && (flags & (1u<<2)) && pkgfilter && foundpackage)
{ //if we're using full package paths, and we're trying to force the search, then be prepared to search gamedirs which are not currently active too if we didn't already search it.
// searchpath_t dummy;
// dummy.filename =
Con_Printf("search_begin: SB_FORCESEARCH not supported\n");
}
} }
static qboolean COM_AddPackage(searchpath_t *basepath, const char *pakfile) static qboolean COM_AddPackage(searchpath_t *basepath, const char *pakfile, const char *purename)
{ {
searchpath_t *search; searchpath_t *search;
pack_t *pak; pack_t *pak;
@ -2583,6 +2609,8 @@ static qboolean COM_AddPackage(searchpath_t *basepath, const char *pakfile)
} }
search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t)); search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
q_strlcpy(search->filename, pakfile, sizeof(search->filename));
q_strlcpy(search->purename, purename, sizeof(search->purename));
search->path_id = basepath->path_id; search->path_id = basepath->path_id;
search->pack = pak; search->pack = pak;
search->next = com_searchpaths; search->next = com_searchpaths;
@ -2595,8 +2623,10 @@ static qboolean COM_AddEnumeratedPackage(void *ctx, const char *pakfile)
{ {
searchpath_t *basepath = ctx; searchpath_t *basepath = ctx;
char fullpakfile[MAX_OSPATH]; char fullpakfile[MAX_OSPATH];
char purepakfile[MAX_OSPATH];
q_snprintf (fullpakfile, sizeof(fullpakfile), "%s/%s", basepath->filename, pakfile); q_snprintf (fullpakfile, sizeof(fullpakfile), "%s/%s", basepath->filename, pakfile);
return COM_AddPackage(basepath, fullpakfile); q_snprintf (purepakfile, sizeof(purepakfile), "%s/%s", basepath->purename, pakfile);
return COM_AddPackage(basepath, fullpakfile, purepakfile);
} }
const char *COM_GetGameNames(qboolean full) const char *COM_GetGameNames(qboolean full)
@ -2662,6 +2692,7 @@ static void COM_AddGameDirectory (const char *dir)
unsigned int path_id; unsigned int path_id;
searchpath_t *searchdir; searchpath_t *searchdir;
char pakfile[MAX_OSPATH]; char pakfile[MAX_OSPATH];
char purename[MAX_OSPATH];
qboolean been_here = false; qboolean been_here = false;
FILE *listing; FILE *listing;
qboolean found; qboolean found;
@ -2699,6 +2730,7 @@ _add_path:
searchdir = (searchpath_t *) Z_Malloc(sizeof(searchpath_t)); searchdir = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
searchdir->path_id = path_id; searchdir->path_id = path_id;
q_strlcpy (searchdir->filename, com_gamedir, sizeof(searchdir->filename)); q_strlcpy (searchdir->filename, com_gamedir, sizeof(searchdir->filename));
q_strlcpy (searchdir->purename, dir, sizeof(searchdir->purename));
q_snprintf (pakfile, sizeof(pakfile), "%s/pak.lst", com_gamedir); q_snprintf (pakfile, sizeof(pakfile), "%s/pak.lst", com_gamedir);
listing = fopen(pakfile, "rb"); listing = fopen(pakfile, "rb");
@ -2724,14 +2756,16 @@ _add_path:
if (strchr(com_token, '/') || strchr(com_token, '\\') || strchr(com_token, ':')) if (strchr(com_token, '/') || strchr(com_token, '\\') || strchr(com_token, ':'))
continue; continue;
q_snprintf (pakfile, sizeof(pakfile), "%s/%s", com_gamedir, com_token); q_snprintf (pakfile, sizeof(pakfile), "%s/%s", com_gamedir, com_token);
COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s/%s", dir, com_token);
COM_AddPackage(searchdir, pakfile, purename);
if (path_id == 1 && !fitzmode && !q_strncasecmp(com_token, "pak0.", 5)) if (path_id == 1 && !fitzmode && !q_strncasecmp(com_token, "pak0.", 5))
{ //add this now, to try to retain correct ordering. { //add this now, to try to retain correct ordering.
qboolean old = com_modified; qboolean old = com_modified;
if (been_here) base = host_parms->userdir; if (been_here) base = host_parms->userdir;
q_snprintf (pakfile, sizeof(pakfile), "%s/%s.%s", base, enginepackname, COM_FileGetExtension(com_token)); q_snprintf (pakfile, sizeof(pakfile), "%s/%s.%s", base, enginepackname, COM_FileGetExtension(com_token));
COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s.%s", enginepackname, COM_FileGetExtension(com_token));
COM_AddPackage(searchdir, pakfile, purename);
com_modified = old; com_modified = old;
} }
} }
@ -2743,9 +2777,11 @@ _add_path:
found = false; found = false;
q_snprintf (pakfile, sizeof(pakfile), "%s/pak%i.pak", com_gamedir, i); q_snprintf (pakfile, sizeof(pakfile), "%s/pak%i.pak", com_gamedir, i);
found |= COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s/pak%i.pak", dir, i);
found |= COM_AddPackage(searchdir, pakfile, purename);
q_snprintf (pakfile, sizeof(pakfile), "%s/pak%i.pk3", com_gamedir, i); q_snprintf (pakfile, sizeof(pakfile), "%s/pak%i.pk3", com_gamedir, i);
found |= COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s/pak%i.pk3", dir, i);
found |= COM_AddPackage(searchdir, pakfile, purename);
if (i == 0 && path_id == 1 && !fitzmode) if (i == 0 && path_id == 1 && !fitzmode)
{ {
@ -2753,9 +2789,11 @@ _add_path:
if (been_here) base = host_parms->userdir; if (been_here) base = host_parms->userdir;
q_snprintf (pakfile, sizeof(pakfile), "%s/%s.pak", base, enginepackname); q_snprintf (pakfile, sizeof(pakfile), "%s/%s.pak", base, enginepackname);
COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s.pak", enginepackname);
COM_AddPackage(searchdir, pakfile, purename);
q_snprintf (pakfile, sizeof(pakfile), "%s/%s.pk3", base, enginepackname); q_snprintf (pakfile, sizeof(pakfile), "%s/%s.pk3", base, enginepackname);
COM_AddPackage(searchdir, pakfile); q_snprintf (purename, sizeof(purename), "%s.pk3", enginepackname);
COM_AddPackage(searchdir, pakfile, purename);
com_modified = old; com_modified = old;
} }

View File

@ -239,6 +239,7 @@ typedef struct searchpath_s
// Note that <install_dir>/game1 and // Note that <install_dir>/game1 and
// <userdir>/game1 have the same id. // <userdir>/game1 have the same id.
char filename[MAX_OSPATH]; char filename[MAX_OSPATH];
char purename[MAX_OSPATH]; // 'gamedir[/foo.pak]'
pack_t *pack; // only one of filename / pack will be used pack_t *pack; // only one of filename / pack will be used
struct searchpath_s *next; struct searchpath_s *next;
} searchpath_t; } searchpath_t;
@ -253,7 +254,7 @@ extern char com_basedir[MAX_OSPATH];
extern char com_gamedir[MAX_OSPATH]; extern char com_gamedir[MAX_OSPATH];
extern int file_from_pak; // global indicating that file came from a pak extern int file_from_pak; // global indicating that file came from a pak
void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath)); void COM_ListAllFiles(void *ctx, const char *pattern, qboolean (*cb)(void *ctx, const char *fname, time_t mtime, size_t fsize, searchpath_t *spath), unsigned int flags, const char *pkgfilter);
const char *COM_GetGameNames(qboolean full); const char *COM_GetGameNames(qboolean full);
qboolean COM_GameDirMatches(const char *tdirs); qboolean COM_GameDirMatches(const char *tdirs);

View File

@ -3146,14 +3146,14 @@ static void PF_search_begin(void)
const char *pattern = G_STRING(OFS_PARM0); const char *pattern = G_STRING(OFS_PARM0);
unsigned int flags = G_FLOAT(OFS_PARM1); unsigned int flags = G_FLOAT(OFS_PARM1);
// qboolaen quiet = !!G_FLOAT(OFS_PARM2); // qboolaen quiet = !!G_FLOAT(OFS_PARM2);
// const char *pkgfilter = G_STRING(OFS_PARM3); const char *pkgfilter = (qcvm->argc>3)?G_STRING(OFS_PARM3):NULL;
for (i = 0; i < countof(searches); i++) for (i = 0; i < countof(searches); i++)
{ {
if (!searches[i].owner) if (!searches[i].owner)
{ {
searches[i].flags = flags; searches[i].flags = flags;
COM_ListAllFiles(&searches[i], pattern, PR_Search_AddFile); COM_ListAllFiles(&searches[i], pattern, PR_Search_AddFile, flags, pkgfilter);
if (!searches[i].numfiles) if (!searches[i].numfiles)
break; break;
searches[i].owner = qcvm; searches[i].owner = qcvm;
@ -3241,28 +3241,12 @@ static void PF_search_getpackagename(void)
{ {
if (searches[handle].flags & 2) if (searches[handle].flags & 2)
{ //gamedir/packagename. not necessarily fopenable. { //gamedir/packagename. not necessarily fopenable.
if (spath->pack) G_INT(OFS_RETURN) = PR_MakeTempString(spath->purename);
{
const char *pathname = spath->pack->filename;
const char *last = pathname, *last2 = "";
while (*pathname)
{
if (*pathname == '/')
{
last2 = last;
last = pathname + 1;
}
pathname++;
}
G_INT(OFS_RETURN) = PR_MakeTempString(last2);
}
else
G_INT(OFS_RETURN) = PR_MakeTempString(COM_SkipPath(spath->filename));
} }
else else
{ //like whichpack thus like frik_file. which sucks. { //like whichpack thus like frik_file. which sucks.
if (spath->pack) if (spath->pack)
G_INT(OFS_RETURN) = PR_MakeTempString(COM_SkipPath(spath->pack->filename)); G_INT(OFS_RETURN) = PR_MakeTempString(COM_SkipPath(spath->purename));
else else
G_INT(OFS_RETURN) = 0; G_INT(OFS_RETURN) = 0;
} }
@ -7116,7 +7100,7 @@ static struct
{"argv", PF_ArgV, PF_ArgV, 442, PF_ArgV,59, "string(float n)"},// (KRIMZON_SV_PARSECLIENTCOMMAND {"argv", PF_ArgV, PF_ArgV, 442, PF_ArgV,59, "string(float n)"},// (KRIMZON_SV_PARSECLIENTCOMMAND
{"argc", PF_ArgC, PF_ArgC, 0, PF_ArgC,0, "float()"}, {"argc", PF_ArgC, PF_ArgC, 0, PF_ArgC,0, "float()"},
{"setattachment", PF_setattachment, PF_setattachment, 443, PF_NoMenu, "void(entity e, entity tagentity, string tagname)", ""},// (DP_GFX_QUAKE3MODELTAGS) {"setattachment", PF_setattachment, PF_setattachment, 443, PF_NoMenu, "void(entity e, entity tagentity, string tagname)", ""},// (DP_GFX_QUAKE3MODELTAGS)
{"search_begin", PF_search_begin, PF_search_begin, 444, PF_search_begin,74, "searchhandle(string pattern, optional float caseinsensitive, optional float quiet)", "initiate a filesystem scan based upon filenames. Be sure to call search_end on the returned handle."}, {"search_begin", PF_search_begin, PF_search_begin, 444, PF_search_begin,74, "searchhandle(string pattern, float flags, float quiet, optional string filterpackage)", "initiate a filesystem scan based upon filenames. Be sure to call search_end on the returned handle."},
{"search_end", PF_search_end, PF_search_end, 445, PF_search_end,75, "void(searchhandle handle)", ""}, {"search_end", PF_search_end, PF_search_end, 445, PF_search_end,75, "void(searchhandle handle)", ""},
{"search_getsize", PF_search_getsize, PF_search_getsize, 446, PF_search_getsize,76, "float(searchhandle handle)", " Retrieves the number of files that were found."}, {"search_getsize", PF_search_getsize, PF_search_getsize, 446, PF_search_getsize,76, "float(searchhandle handle)", " Retrieves the number of files that were found."},
{"search_getfilename",PF_search_getfilename,PF_search_getfilename,447,PF_search_getfilename,77, "string(searchhandle handle, float num)", "Retrieves name of one of the files that was found by the initial search."}, {"search_getfilename",PF_search_getfilename,PF_search_getfilename,447,PF_search_getfilename,77, "string(searchhandle handle, float num)", "Retrieves name of one of the files that was found by the initial search."},
@ -7217,14 +7201,14 @@ static struct
// {"generateentitydata",PF_generateentitydata,NULL, 0, PF_NoMenu, D("string(entity e)", "Dumps the entities fields into a string which can later be parsed with parseentitydata."}), // {"generateentitydata",PF_generateentitydata,NULL, 0, PF_NoMenu, D("string(entity e)", "Dumps the entities fields into a string which can later be parsed with parseentitydata."}),
{"getgamedirinfo", PF_NoSSQC, PF_NoCSQC, 626, PF_getgamedirinfo,626, D("string(float n, float prop)", "Provides a way to enumerate available mod directories.")}, {"getgamedirinfo", PF_NoSSQC, PF_getgamedirinfo, 626, PF_getgamedirinfo,626, D("string(float n, float prop)", "Provides a way to enumerate available mod directories.")},
{"sprintf", PF_sprintf, PF_sprintf, 627, PF_sprintf,627, "string(string fmt, ...)"}, {"sprintf", PF_sprintf, PF_sprintf, 627, PF_sprintf,627, "string(string fmt, ...)"},
{"getsurfacenumtriangles",PF_getsurfacenumtriangles,PF_getsurfacenumtriangles,628,PF_NoMenu, "float(entity e, float s)"}, {"getsurfacenumtriangles",PF_getsurfacenumtriangles,PF_getsurfacenumtriangles,628,PF_NoMenu, "float(entity e, float s)"},
{"getsurfacetriangle",PF_getsurfacetriangle,PF_getsurfacetriangle, 629, PF_NoMenu, "vector(entity e, float s, float n)"}, {"getsurfacetriangle",PF_getsurfacetriangle,PF_getsurfacetriangle, 629, PF_NoMenu, "vector(entity e, float s, float n)"},
{"setkeybind", PF_NoSSQC, PF_cl_setkeybind, 630, PF_cl_setkeybind,630, "float(float key, string bind, optional float bindmap)", "Changes a key binding."}, {"setkeybind", PF_NoSSQC, PF_cl_setkeybind, 630, PF_cl_setkeybind,630, "float(float key, string bind, optional float bindmap, optional float modifier)", "Changes a key binding."},
{"getbindmaps", PF_NoSSQC, PF_cl_getbindmaps, 631, PF_cl_getbindmaps,631, "vector()", "stub."}, {"getbindmaps", PF_NoSSQC, PF_cl_getbindmaps, 631, PF_cl_getbindmaps,631, "vector()", "stub."},
{"setbindmaps", PF_NoSSQC, PF_cl_setbindmaps, 632, PF_cl_setbindmaps,632, "float(vector bm)", "stub."}, {"setbindmaps", PF_NoSSQC, PF_cl_setbindmaps, 632, PF_cl_setbindmaps,632, "float(vector bm)", "stub."},
{"digest_hex", PF_digest_hex, PF_digest_hex, 639, PF_digest_hex, 639, "string(string digest, string data, ...)", "stub."}, {"digest_hex", PF_digest_hex, PF_digest_hex, 639, PF_digest_hex, 639, "string(string digest, string data, ...)"},
}; };
static const char *extnames[] = static const char *extnames[] =