Add basic support for ktx's 'mapname#modifier' ent stuff.
This commit is contained in:
parent
774fb93721
commit
1fe478dfa1
6 changed files with 113 additions and 8 deletions
|
@ -184,6 +184,8 @@ void Mod_ParseEntities(struct model_s *mod);
|
|||
void Mod_LoadMapArchive(struct model_s *mod, void *archivedata, size_t archivesize);
|
||||
extern void Mod_ClearAll (void);
|
||||
extern void Mod_Purge (enum mod_purge_e type);
|
||||
extern void Mod_SetModifier (const char *modifier);
|
||||
extern char mod_modifier[];
|
||||
extern qboolean Mod_PurgeModel (struct model_s *mod, enum mod_purge_e ptype);
|
||||
extern struct model_s *Mod_FindName (const char *name); //find without loading. needload should be set.
|
||||
extern struct model_s *Mod_ForName (const char *name, enum mlverbosity_e verbosity); //finds+loads
|
||||
|
|
|
@ -7930,6 +7930,7 @@ void Mod_Terrain_Save_f(void)
|
|||
{
|
||||
//warning: brushes are not saved unless its a .map
|
||||
COM_StripExtension(mod->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
|
||||
FS_CreatePath(fname, FS_GAMEONLY);
|
||||
|
|
|
@ -81,6 +81,7 @@ void Mod_LoadDoomSprite (model_t *mod);
|
|||
#define MAX_MOD_KNOWN 8192
|
||||
model_t *mod_known;
|
||||
int mod_numknown;
|
||||
char mod_modifier[MAX_QPATH]; //postfix for ent files
|
||||
|
||||
extern cvar_t r_loadlits;
|
||||
#ifdef SPECULAR
|
||||
|
@ -620,6 +621,17 @@ void Mod_Purge(enum mod_purge_e ptype)
|
|||
}
|
||||
}
|
||||
|
||||
void Mod_SetModifier(const char *modifier)
|
||||
{
|
||||
if (!modifier || strlen(modifier) >= sizeof(mod_modifier)) modifier = "";
|
||||
if (strcmp(modifier, mod_modifier))
|
||||
{ //if the modifier changed, force all models to reset.
|
||||
COM_WorkerFullSync(); //sync all the workers, just in case.
|
||||
strcpy(mod_modifier, modifier);
|
||||
Mod_Purge(MP_RESET); //nuke it now
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
void Mod_FindCubemaps_f(void);
|
||||
void Mod_Realign_f(void);
|
||||
|
@ -2252,11 +2264,13 @@ static void Mod_SaveEntFile_f(void)
|
|||
{
|
||||
Q_snprintfz(fname, sizeof(fname), "maps/%s/%s", mod_loadentfiles_dir.string, mod->name+5);
|
||||
COM_StripExtension(fname, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_StripExtension(mod->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
}
|
||||
|
||||
|
@ -2293,6 +2307,7 @@ qboolean Mod_LoadEntitiesBlob(struct model_s *mod, const char *entdata, size_t e
|
|||
{
|
||||
Q_snprintfz(fname, sizeof(fname), "maps/%s/%s", mod_loadentfiles_dir.string, mod->name+5);
|
||||
COM_StripExtension(fname, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
ents = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
|
@ -2300,12 +2315,14 @@ qboolean Mod_LoadEntitiesBlob(struct model_s *mod, const char *entdata, size_t e
|
|||
if (mod_loadentfiles.value && !ents)
|
||||
{
|
||||
COM_StripExtension(mod->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".ent", sizeof(fname));
|
||||
ents = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
if (mod_loadentfiles.value && !ents)
|
||||
{ //tenebrae compat
|
||||
COM_StripExtension(mod->name, fname, sizeof(fname));
|
||||
Q_strncatz(fname, mod_modifier, sizeof(fname));
|
||||
Q_strncatz(fname, ".edo", sizeof(fname));
|
||||
ents = FS_LoadMallocFile(fname, &sz);
|
||||
}
|
||||
|
|
|
@ -1090,11 +1090,21 @@ static qintptr_t QVM_SetSpawnParams (void *offset, quintptr_t mask, const qintpt
|
|||
static qintptr_t QVM_ChangeLevel (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
const char *arg_mapname = VM_POINTER(arg[0]);
|
||||
// const char *arg_entfilename = VM_POINTER(arg[1]);
|
||||
const char *arg_entfilename = (qvm_api_version > 13)?(VM_POINTER(arg[1])):"";
|
||||
|
||||
char newmap[MAX_QPATH];
|
||||
if (sv.mapchangelocked)
|
||||
return 0;
|
||||
|
||||
if (arg_entfilename && *arg_entfilename)
|
||||
{
|
||||
int nl = strlen(arg_mapname);
|
||||
if (!strncmp(arg_mapname, arg_entfilename, nl) && arg_mapname[nl]=='#')
|
||||
arg_mapname = arg_entfilename;
|
||||
else
|
||||
Con_Printf(CON_ERROR"%s: named ent file does not match map\n", "QVM_ChangeLevel");
|
||||
}
|
||||
|
||||
sv.mapchangelocked = true;
|
||||
COM_QuotedString(arg_mapname, newmap, sizeof(newmap), false);
|
||||
Cbuf_AddText (va("\nchangelevel %s\n", newmap), RESTRICT_LOCAL);
|
||||
|
@ -1103,13 +1113,23 @@ static qintptr_t QVM_ChangeLevel (void *offset, quintptr_t mask, const qintptr_t
|
|||
static qintptr_t QVM_ChangeLevelHub (void *offset, quintptr_t mask, const qintptr_t *arg)
|
||||
{
|
||||
const char *arg_mapname = VM_POINTER(arg[0]);
|
||||
// const char *arg_entfile = VM_POINTER(arg[1]);
|
||||
const char *arg_entfilename = VM_POINTER(arg[1]);
|
||||
const char *arg_startspot = VM_POINTER(arg[2]);
|
||||
|
||||
char newmap[MAX_QPATH];
|
||||
char startspot[MAX_QPATH];
|
||||
if (sv.mapchangelocked)
|
||||
return 0;
|
||||
|
||||
if (arg_entfilename && *arg_entfilename)
|
||||
{
|
||||
int nl = strlen(arg_mapname);
|
||||
if (!strncmp(arg_mapname, arg_entfilename, nl) && arg_mapname[nl]=='#')
|
||||
arg_mapname = arg_entfilename;
|
||||
else
|
||||
Con_Printf(CON_ERROR"%s: named ent file does not match map\n", "QVM_ChangeLevelHub");
|
||||
}
|
||||
|
||||
sv.mapchangelocked = true;
|
||||
COM_QuotedString(arg_mapname, newmap, sizeof(newmap), false);
|
||||
COM_QuotedString(arg_startspot, startspot, sizeof(startspot), false);
|
||||
|
|
|
@ -471,6 +471,27 @@ static int QDECL CompleteMapList (const char *name, qofs_t flags, time_t mtime,
|
|||
ctx->cb(stripped, NULL, NULL, ctx);
|
||||
return true;
|
||||
}
|
||||
static int QDECL CompleteMapListEnt (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||
{
|
||||
struct xcommandargcompletioncb_s *ctx = parm;
|
||||
char stripped[64];
|
||||
char *modifier = strchr(name, '#');
|
||||
if (!modifier) //skip non-modifiers.
|
||||
return true;
|
||||
if (modifier-name+4 > sizeof(stripped)) //too long...
|
||||
return true;
|
||||
|
||||
//make sure we have its .bsp
|
||||
memcpy(stripped, name, modifier-name);
|
||||
strcpy(stripped+(modifier-name), ".bsp");
|
||||
if (!COM_FCheckExists(stripped))
|
||||
return true;
|
||||
|
||||
COM_StripExtension(name+5, stripped, sizeof(stripped));
|
||||
ctx->cb(stripped, NULL, NULL, ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int QDECL CompleteMapListExt (const char *name, qofs_t flags, time_t mtime, void *parm, searchpathfuncs_t *spath)
|
||||
{
|
||||
struct xcommandargcompletioncb_s *ctx = parm;
|
||||
|
@ -493,6 +514,8 @@ static void SV_Map_c(int argn, const char *partial, struct xcommandargcompletion
|
|||
COM_EnumerateFiles(va("maps/%s*.cm", partial), CompleteMapList, ctx);
|
||||
COM_EnumerateFiles(va("maps/%s*.hmp", partial), CompleteMapList, ctx);
|
||||
|
||||
COM_EnumerateFiles(va("maps/%s*.ent", partial), CompleteMapListEnt, ctx);
|
||||
|
||||
COM_EnumerateFiles(va("maps/%s*/*.bsp", partial), CompleteMapList, ctx);
|
||||
COM_EnumerateFiles(va("maps/%s*/*.bsp.gz", partial), CompleteMapListExt, ctx);
|
||||
COM_EnumerateFiles(va("maps/%s*/*.bsp.xz", partial), CompleteMapListExt, ctx);
|
||||
|
@ -609,7 +632,7 @@ fte:
|
|||
'map package:mapname' should download the specified map package and load up its maps.
|
||||
|
||||
mvdsv:
|
||||
basemap#modifier.ent files
|
||||
'map foo bar' should load 'maps/bar.ent' instead of the regular ent file. this 'bar' will usually be something like 'foo#modified'
|
||||
|
||||
======================
|
||||
*/
|
||||
|
@ -851,10 +874,25 @@ void SV_Map_f (void)
|
|||
break;
|
||||
}
|
||||
if (!exts[i])
|
||||
{ //try again.
|
||||
char *mod = strchr(level, '#');
|
||||
if (mod)
|
||||
{
|
||||
*mod = 0;
|
||||
for (i = 0; exts[i]; i++)
|
||||
{
|
||||
snprintf (expanded, sizeof(expanded), exts[i], level);
|
||||
if (COM_FCheckExists (expanded))
|
||||
break;
|
||||
}
|
||||
*mod = '#';
|
||||
}
|
||||
}
|
||||
if (!exts[i])
|
||||
{
|
||||
for (i = 0; exts[i]; i++)
|
||||
{
|
||||
//doesn't exist, so try lowercase. Q3 does this.
|
||||
//doesn't exist, so try lowercase. Q3 does this. really our fs_cache stuff should be handling this, but its possible its disabled.
|
||||
for (j = 0; j < sizeof(level) && level[j]; j++)
|
||||
{
|
||||
if (level[j] >= 'A' && level[j] <= 'Z')
|
||||
|
|
|
@ -1016,12 +1016,11 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
|||
{
|
||||
//.map is commented out because quite frankly, they're a bit annoying when the engine loads the gpled start.map when really you wanted to just play the damn game intead of take it apart.
|
||||
//if you want to load a .map, just use 'map foo.map' instead.
|
||||
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ "maps/%s.bsp.gz", "maps/%s.bsp.xz", NULL}, *e;
|
||||
int depth, bestdepth;
|
||||
char *exts[] = {"%s", "maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ "maps/%s.bsp.gz", "maps/%s.bsp.xz", NULL}, *e;
|
||||
int depth, bestdepth = FDEPTH_MISSING;
|
||||
flocation_t loc;
|
||||
time_t filetime;
|
||||
Q_snprintfz (sv.modelname, sizeof(sv.modelname), "%s", server);
|
||||
bestdepth = COM_FDepthFile(sv.modelname, false);
|
||||
char *mod = NULL;
|
||||
if (bestdepth == FDEPTH_MISSING)
|
||||
{ //not an exact name, scan the maps subdir.
|
||||
for (i = 0; exts[i]; i++)
|
||||
|
@ -1034,6 +1033,32 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (bestdepth == FDEPTH_MISSING)
|
||||
{
|
||||
mod = strchr(server, '#');
|
||||
if (mod)
|
||||
{
|
||||
*mod = 0;
|
||||
bestdepth = COM_FDepthFile(server, false);
|
||||
if (bestdepth != FDEPTH_MISSING)
|
||||
Q_snprintfz (sv.modelname, sizeof(sv.modelname), "%s", server);
|
||||
else
|
||||
{ //not an exact name, scan the maps subdir.
|
||||
for (i = 0; exts[i]; i++)
|
||||
{
|
||||
depth = COM_FDepthFile(va(exts[i], server), false);
|
||||
if (depth < bestdepth)
|
||||
{
|
||||
bestdepth = depth;
|
||||
Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[i], server);
|
||||
}
|
||||
}
|
||||
}
|
||||
*mod = '#';
|
||||
if (bestdepth == FDEPTH_MISSING)
|
||||
mod = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strncmp(sv.modelname, "maps/", 5))
|
||||
Q_strncpyz (svs.name, sv.modelname+5, sizeof(svs.name));
|
||||
|
@ -1048,6 +1073,8 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
|
|||
if (!strcmp(e, ".bsp"))
|
||||
*e = 0;
|
||||
|
||||
Mod_SetModifier(mod);
|
||||
|
||||
sv.world.worldmodel = Mod_ForName (sv.modelname, MLV_ERROR);
|
||||
|
||||
if (FS_FLocateFile(sv.modelname,FSLF_IFFOUND, &loc) && FS_GetLocMTime(&loc, &filetime))
|
||||
|
|
Loading…
Reference in a new issue