Allow manifests to provide signatures for packages. Restart the menus when a package with a menu.dat is enabled.
This commit is contained in:
parent
c5f837d468
commit
a5232cfecd
3 changed files with 99 additions and 7 deletions
|
@ -2093,26 +2093,26 @@ void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const cha
|
||||||
pri = maxpri;
|
pri = maxpri;
|
||||||
for (p = availablepackages; p; p = p->next)
|
for (p = availablepackages; p; p = p->next)
|
||||||
{
|
{
|
||||||
if ((p->flags & DPF_ENABLED) && p->qhash && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority>=minpri&&p->priority<pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||||
pri = p->priority;
|
pri = p->priority;
|
||||||
}
|
}
|
||||||
minpri = pri+1;
|
minpri = pri+1;
|
||||||
|
|
||||||
for (p = availablepackages; p; p = p->next)
|
for (p = availablepackages; p; p = p->next)
|
||||||
{
|
{
|
||||||
if ((p->flags & DPF_ENABLED) && p->qhash && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
if ((p->flags & (DPF_ENABLED|DPF_MANIMARKED)) && p->qhash && p->priority==pri && !Q_strcasecmp(parent_pure, p->gamedir))
|
||||||
{
|
{
|
||||||
for (d = p->deps; d; d = d->next)
|
for (d = p->deps; d; d = d->next)
|
||||||
{
|
{
|
||||||
if (d->dtype == DEP_FILE)
|
if (d->dtype == DEP_FILE)
|
||||||
{
|
{
|
||||||
Q_snprintfz(temp, sizeof(temp), "%s/%s", p->gamedir, d->name);
|
Q_snprintfz(temp, sizeof(temp), "%s/%s", p->gamedir, d->name);
|
||||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|SPF_UNTRUSTED);
|
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, search, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
|
||||||
}
|
}
|
||||||
else if (d->dtype == DEP_CACHEFILE)
|
else if (d->dtype == DEP_CACHEFILE)
|
||||||
{
|
{
|
||||||
Q_snprintfz(temp, sizeof(temp), "downloads/%s", d->name);
|
Q_snprintfz(temp, sizeof(temp), "downloads/%s", d->name);
|
||||||
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|SPF_UNTRUSTED);
|
FS_AddHashedPackage(oldpaths, parent_pure, parent_logical, NULL, loadstuff, temp, *p->qhash?p->qhash:NULL, p->packprefix, SPF_COPYPROTECTED|((p->flags & DPF_SIGNATUREACCEPTED)?0:SPF_UNTRUSTED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3270,6 +3270,7 @@ static void PM_PackageEnabled(package_t *p)
|
||||||
if (dep->dtype != DEP_FILE && dep->dtype != DEP_CACHEFILE)
|
if (dep->dtype != DEP_FILE && dep->dtype != DEP_CACHEFILE)
|
||||||
continue;
|
continue;
|
||||||
COM_FileExtension(dep->name, ext, sizeof(ext));
|
COM_FileExtension(dep->name, ext, sizeof(ext));
|
||||||
|
if (!pm_packagesinstalled)
|
||||||
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3") || !stricmp(ext, "zip"))
|
if (!stricmp(ext, "pak") || !stricmp(ext, "pk3") || !stricmp(ext, "zip"))
|
||||||
{
|
{
|
||||||
if (pm_packagesinstalled)
|
if (pm_packagesinstalled)
|
||||||
|
@ -3420,6 +3421,10 @@ static qboolean PM_Download_Got_Extract(package_t *p, searchpathfuncs_t *archive
|
||||||
archive->ReadFile(archive, &loc, f);
|
archive->ReadFile(archive, &loc, f);
|
||||||
if (FS_WriteFile(destname, f, loc.len, p->fsroot))
|
if (FS_WriteFile(destname, f, loc.len, p->fsroot))
|
||||||
{
|
{
|
||||||
|
if (!FS_NativePath(destname, p->fsroot, native, sizeof(native)))
|
||||||
|
Q_strncpyz(native, destname, sizeof(native));
|
||||||
|
Con_Printf("Extracted %s (to %s)\n", p->name, native);
|
||||||
|
|
||||||
p->flags = nfl;
|
p->flags = nfl;
|
||||||
success = true;
|
success = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -4672,6 +4677,17 @@ void PM_Command_f(void)
|
||||||
Con_Printf(" ^[[Add]\\type\\pkg add %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
|
Con_Printf(" ^[[Add]\\type\\pkg add %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
|
||||||
if ((p->flags&DPF_MARKED) && p == PM_MarkedPackage(p->name, DPF_MARKED))
|
if ((p->flags&DPF_MARKED) && p == PM_MarkedPackage(p->name, DPF_MARKED))
|
||||||
Con_Printf(" ^[[Remove]\\type\\pkg rem %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
|
Con_Printf(" ^[[Remove]\\type\\pkg rem %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
|
||||||
|
|
||||||
|
|
||||||
|
if (p->flags & DPF_SIGNATUREACCEPTED)
|
||||||
|
Con_Printf(" ^&02Trusted");
|
||||||
|
else if (p->flags & DPF_SIGNATUREREJECTED)
|
||||||
|
Con_Printf(" ^&04Untrusted");
|
||||||
|
else if (p->flags & DPF_SIGNATUREUNKNOWN)
|
||||||
|
Con_Printf(" ^&0EUnverified");
|
||||||
|
else
|
||||||
|
Con_Printf(" ^&0EUnsigned");
|
||||||
|
|
||||||
Con_Printf("\n");
|
Con_Printf("\n");
|
||||||
}
|
}
|
||||||
Z_Free(sorted);
|
Z_Free(sorted);
|
||||||
|
@ -5041,6 +5057,15 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
||||||
p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED;
|
p->flags = DPF_FORGETONUNINSTALL|DPF_MANIFEST|DPF_GUESSED;
|
||||||
p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL;
|
p->qhash = pack->crcknown?Z_StrDupf("%#x", pack->crc):NULL;
|
||||||
|
|
||||||
|
//note that this signs the hash(validated with size) with an separately trusted authority and is thus not dependant upon trusting the manifest itself...
|
||||||
|
//that said, we can't necessarily trust any overrides the manifest might include - those parts do not form part of the signature.
|
||||||
|
if (!pack->prefix && pack->crcknown && strchr(p->name, '/'))
|
||||||
|
{
|
||||||
|
p->signature = pack->signature?Z_StrDup(pack->signature):NULL;
|
||||||
|
p->filesha512 = pack->sha512?Z_StrDup(pack->sha512):NULL;
|
||||||
|
p->filesize = pack->filesize;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
char *c = p->name;
|
char *c = p->name;
|
||||||
for (c=p->name; *c; c++) //don't get confused.
|
for (c=p->name; *c; c++) //don't get confused.
|
||||||
|
@ -5106,6 +5131,8 @@ void PM_AddManifestPackages(ftemanifest_t *man)
|
||||||
}
|
}
|
||||||
PM_AddDep(p, DEP_FILE, path);
|
PM_AddDep(p, DEP_FILE, path);
|
||||||
|
|
||||||
|
PM_ValidateAuthenticity(p, VH_UNSUPPORTED);
|
||||||
|
|
||||||
m = PM_InsertPackage(p);
|
m = PM_InsertPackage(p);
|
||||||
if (!m)
|
if (!m)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -797,6 +797,9 @@ typedef struct
|
||||||
unsigned int crc; //the public crc
|
unsigned int crc; //the public crc
|
||||||
char *mirrors[8]; //a randomized (prioritized-on-load) list of mirrors to use. (may be 'prompt:game,package', 'unzip:file,url', 'xz:url', 'gz:url'
|
char *mirrors[8]; //a randomized (prioritized-on-load) list of mirrors to use. (may be 'prompt:game,package', 'unzip:file,url', 'xz:url', 'gz:url'
|
||||||
char *condition; //only downloaded if this cvar is set | delimited allows multiple cvars.
|
char *condition; //only downloaded if this cvar is set | delimited allows multiple cvars.
|
||||||
|
char *sha512; //package must match this hash, if specified
|
||||||
|
char *signature; //signs the hash
|
||||||
|
qofs_t filesize;
|
||||||
int mirrornum; //the index we last tried to download from, so we still work even if mirrors are down.
|
int mirrornum; //the index we last tried to download from, so we still work even if mirrors are down.
|
||||||
} package[64];
|
} package[64];
|
||||||
} ftemanifest_t;
|
} ftemanifest_t;
|
||||||
|
|
|
@ -189,7 +189,7 @@ qboolean Sys_ResolveFileURL(const char *inurl, int inlen, char *out, int outlen)
|
||||||
{ //has an authority field...
|
{ //has an authority field...
|
||||||
i+=2;
|
i+=2;
|
||||||
//except we don't support authorities other than ourself...
|
//except we don't support authorities other than ourself...
|
||||||
if (i < inend || *i != '/')
|
if (i >= inend || *i != '/')
|
||||||
return false; //must be an absolute path...
|
return false; //must be an absolute path...
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
i++; //on windows, (full)absolute paths start with a drive name...
|
i++; //on windows, (full)absolute paths start with a drive name...
|
||||||
|
@ -320,6 +320,8 @@ void FS_Manifest_Free(ftemanifest_t *man)
|
||||||
Z_Free(man->package[i].path);
|
Z_Free(man->package[i].path);
|
||||||
Z_Free(man->package[i].prefix);
|
Z_Free(man->package[i].prefix);
|
||||||
Z_Free(man->package[i].condition);
|
Z_Free(man->package[i].condition);
|
||||||
|
Z_Free(man->package[i].sha512);
|
||||||
|
Z_Free(man->package[i].signature);
|
||||||
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
|
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
|
||||||
Z_Free(man->package[i].mirrors[j]);
|
Z_Free(man->package[i].mirrors[j]);
|
||||||
}
|
}
|
||||||
|
@ -372,12 +374,20 @@ static ftemanifest_t *FS_Manifest_Clone(ftemanifest_t *oldm)
|
||||||
}
|
}
|
||||||
for (i = 0; i < sizeof(newm->package) / sizeof(newm->package[0]); i++)
|
for (i = 0; i < sizeof(newm->package) / sizeof(newm->package[0]); i++)
|
||||||
{
|
{
|
||||||
|
newm->package[i].type = oldm->package[i].type;
|
||||||
|
newm->package[i].crc = oldm->package[i].crc;
|
||||||
|
newm->package[i].crcknown = oldm->package[i].crcknown;
|
||||||
if (oldm->package[i].path)
|
if (oldm->package[i].path)
|
||||||
newm->package[i].path = Z_StrDup(oldm->package[i].path);
|
newm->package[i].path = Z_StrDup(oldm->package[i].path);
|
||||||
if (oldm->package[i].prefix)
|
if (oldm->package[i].prefix)
|
||||||
newm->package[i].prefix = Z_StrDup(oldm->package[i].prefix);
|
newm->package[i].prefix = Z_StrDup(oldm->package[i].prefix);
|
||||||
if (oldm->package[i].condition)
|
if (oldm->package[i].condition)
|
||||||
newm->package[i].condition = Z_StrDup(oldm->package[i].condition);
|
newm->package[i].condition = Z_StrDup(oldm->package[i].condition);
|
||||||
|
if (oldm->package[i].sha512)
|
||||||
|
newm->package[i].sha512 = Z_StrDup(oldm->package[i].sha512);
|
||||||
|
if (oldm->package[i].signature)
|
||||||
|
newm->package[i].signature = Z_StrDup(oldm->package[i].signature);
|
||||||
|
newm->package[i].filesize = oldm->package[i].filesize;
|
||||||
for (j = 0; j < sizeof(newm->package[i].mirrors) / sizeof(newm->package[i].mirrors[0]); j++)
|
for (j = 0; j < sizeof(newm->package[i].mirrors) / sizeof(newm->package[i].mirrors[0]); j++)
|
||||||
if (oldm->package[i].mirrors[j])
|
if (oldm->package[i].mirrors[j])
|
||||||
newm->package[i].mirrors[j] = Z_StrDup(oldm->package[i].mirrors[j]);
|
newm->package[i].mirrors[j] = Z_StrDup(oldm->package[i].mirrors[j]);
|
||||||
|
@ -483,10 +493,16 @@ static void FS_Manifest_Print(ftemanifest_t *man)
|
||||||
else
|
else
|
||||||
Con_Printf("package ");
|
Con_Printf("package ");
|
||||||
Con_Printf("%s", COM_QuotedString(man->package[i].path, buffer, sizeof(buffer), false));
|
Con_Printf("%s", COM_QuotedString(man->package[i].path, buffer, sizeof(buffer), false));
|
||||||
if (man->package[i].condition)
|
if (man->package[i].prefix)
|
||||||
Con_Printf(" prefix %s", COM_QuotedString(man->package[i].condition, buffer, sizeof(buffer), false));
|
Con_Printf(" prefix %s", COM_QuotedString(man->package[i].prefix, buffer, sizeof(buffer), false));
|
||||||
if (man->package[i].condition)
|
if (man->package[i].condition)
|
||||||
Con_Printf(" condition %s", COM_QuotedString(man->package[i].condition, buffer, sizeof(buffer), false));
|
Con_Printf(" condition %s", COM_QuotedString(man->package[i].condition, buffer, sizeof(buffer), false));
|
||||||
|
if (man->package[i].filesize)
|
||||||
|
Con_Printf(" filesize %"PRIuQOFS, man->package[i].filesize);
|
||||||
|
if (man->package[i].sha512)
|
||||||
|
Con_Printf(" sha512 %s", COM_QuotedString(man->package[i].sha512, buffer, sizeof(buffer), false));
|
||||||
|
if (man->package[i].signature)
|
||||||
|
Con_Printf(" signature %s", COM_QuotedString(man->package[i].signature, buffer, sizeof(buffer), false));
|
||||||
if (man->package[i].crcknown)
|
if (man->package[i].crcknown)
|
||||||
Con_Printf(" crc 0x%x", man->package[i].crc);
|
Con_Printf(" crc 0x%x", man->package[i].crc);
|
||||||
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
|
for (j = 0; j < sizeof(man->package[i].mirrors) / sizeof(man->package[i].mirrors[0]); j++)
|
||||||
|
@ -552,6 +568,9 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
|
||||||
char *condition = NULL;
|
char *condition = NULL;
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
char *arch = NULL;
|
char *arch = NULL;
|
||||||
|
char *signature = NULL;
|
||||||
|
char *sha512 = NULL;
|
||||||
|
qofs_t filesize = 0;
|
||||||
unsigned int arg = 1;
|
unsigned int arg = 1;
|
||||||
unsigned int mirrors = 0;
|
unsigned int mirrors = 0;
|
||||||
char *mirror[countof(man->package[0].mirrors)];
|
char *mirror[countof(man->package[0].mirrors)];
|
||||||
|
@ -598,6 +617,12 @@ static qboolean FS_Manifest_ParsePackage(ftemanifest_t *man, int packagetype)
|
||||||
prefix = Cmd_Argv(arg++);
|
prefix = Cmd_Argv(arg++);
|
||||||
else if (!strcmp(a, "arch"))
|
else if (!strcmp(a, "arch"))
|
||||||
arch = Cmd_Argv(arg++);
|
arch = Cmd_Argv(arg++);
|
||||||
|
else if (!strcmp(a, "signature"))
|
||||||
|
signature = Cmd_Argv(arg++);
|
||||||
|
else if (!strcmp(a, "sha512"))
|
||||||
|
sha512 = Cmd_Argv(arg++);
|
||||||
|
else if (!strcmp(a, "filesize")||!strcmp(a, "size"))
|
||||||
|
filesize = strtoull(Cmd_Argv(arg++), NULL, 0);
|
||||||
else if (!strcmp(a, "mirror"))
|
else if (!strcmp(a, "mirror"))
|
||||||
{
|
{
|
||||||
a = Cmd_Argv(arg++);
|
a = Cmd_Argv(arg++);
|
||||||
|
@ -642,6 +667,9 @@ mirror:
|
||||||
man->package[i].path = Z_StrDup(path);
|
man->package[i].path = Z_StrDup(path);
|
||||||
man->package[i].prefix = prefix?Z_StrDup(prefix):NULL;
|
man->package[i].prefix = prefix?Z_StrDup(prefix):NULL;
|
||||||
man->package[i].condition = condition?Z_StrDup(condition):NULL;
|
man->package[i].condition = condition?Z_StrDup(condition):NULL;
|
||||||
|
man->package[i].sha512 = sha512?Z_StrDup(sha512):NULL;
|
||||||
|
man->package[i].signature = signature?Z_StrDup(signature):NULL;
|
||||||
|
man->package[i].filesize = filesize;
|
||||||
man->package[i].crcknown = crcknown;
|
man->package[i].crcknown = crcknown;
|
||||||
man->package[i].crc = crc;
|
man->package[i].crc = crc;
|
||||||
for (j = 0; j < mirrors; j++)
|
for (j = 0; j < mirrors; j++)
|
||||||
|
@ -3529,6 +3557,7 @@ void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parentpath, const
|
||||||
|
|
||||||
static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath, const char *logicalpaths, searchpath_t *search, unsigned int loadstuff)
|
static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath, const char *logicalpaths, searchpath_t *search, unsigned int loadstuff)
|
||||||
{
|
{
|
||||||
|
#ifndef PACKAGEMANAGER
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
int ptlen, palen;
|
int ptlen, palen;
|
||||||
|
@ -3552,6 +3581,7 @@ static void FS_AddManifestPackages(searchpath_t **oldpaths, const char *purepath
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FS_AddDownloadManifestPackages(searchpath_t **oldpaths, unsigned int loadstuff)//, const char *purepath, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
|
static void FS_AddDownloadManifestPackages(searchpath_t **oldpaths, unsigned int loadstuff)//, const char *purepath, searchpath_t *search, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc))
|
||||||
|
@ -6141,6 +6171,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
||||||
char *vidfile[] = {"gfx.wad", "gfx/conback.lmp", //misc stuff
|
char *vidfile[] = {"gfx.wad", "gfx/conback.lmp", //misc stuff
|
||||||
"gfx/palette.lmp", "pics/colormap.pcx", "gfx/conchars.png"}; //palettes
|
"gfx/palette.lmp", "pics/colormap.pcx", "gfx/conchars.png"}; //palettes
|
||||||
searchpathfuncs_t *vidpath[countof(vidfile)];
|
searchpathfuncs_t *vidpath[countof(vidfile)];
|
||||||
|
char *menufile[] = {"menu.dat"/*mods*/, "gfx/ttl_main.lmp"/*q1*/, "pics/m_main_quit.pcx"/*q2*/, "gfx/menu/title0.lmp"/*h2*/};
|
||||||
|
searchpathfuncs_t *menupath[countof(menufile)];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//if any of these files change location, the configs will be re-execed.
|
//if any of these files change location, the configs will be re-execed.
|
||||||
|
@ -6159,6 +6191,16 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
||||||
else
|
else
|
||||||
vidpath[i] = NULL;
|
vidpath[i] = NULL;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < countof(menufile); i++)
|
||||||
|
{
|
||||||
|
if (allowreloadconfigs)
|
||||||
|
{
|
||||||
|
FS_FLocateFile(menufile[i], FSLF_IFFOUND|FSLF_SECUREONLY, &loc);
|
||||||
|
menupath[i] = loc.search?loc.search->handle:NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
menupath[i] = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (allowreloadconfigs && fs_noreexec.ival)
|
if (allowreloadconfigs && fs_noreexec.ival)
|
||||||
|
@ -6439,6 +6481,12 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//our basic filesystem should be okay, but no packages loaded yet.
|
||||||
|
#ifdef MANIFESTDOWNLOADS
|
||||||
|
//make sure the package manager knows what its meant to know...
|
||||||
|
PM_AddManifestPackages(man);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Sys_LockMutex(fs_thread_mutex))
|
if (Sys_LockMutex(fs_thread_mutex))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CLIENT
|
#ifdef HAVE_CLIENT
|
||||||
|
@ -6537,6 +6585,20 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
||||||
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
|
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
|
||||||
vidrestart = false;
|
vidrestart = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (qrenderer != QR_NONE && allowreloadconfigs)
|
||||||
|
{
|
||||||
|
for (i = 0; i < countof(menufile); i++)
|
||||||
|
{
|
||||||
|
FS_FLocateFile(menufile[i], FSLF_IFFOUND, &loc);
|
||||||
|
if (menupath[i] != (loc.search?loc.search->handle:NULL))
|
||||||
|
{
|
||||||
|
Cbuf_AddText ("menu_restart\n", RESTRICT_LOCAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//rebuild the cache now, should be safe to waste some cycles on it
|
//rebuild the cache now, should be safe to waste some cycles on it
|
||||||
|
|
Loading…
Reference in a new issue