Skip to content

Commit

Permalink
Add basic support for ktx's 'mapname#modifier' ent stuff.
Browse files Browse the repository at this point in the history
  • Loading branch information
Shpoike committed Apr 17, 2023
1 parent 774fb93 commit 1fe478d
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 8 deletions.
2 changes: 2 additions & 0 deletions engine/client/merged.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions engine/gl/gl_heightmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 17 additions & 0 deletions engine/gl/gl_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -2293,19 +2307,22 @@ 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);
}
}
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);
}
Expand Down
24 changes: 22 additions & 2 deletions engine/server/pr_q1qvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
42 changes: 40 additions & 2 deletions engine/server/sv_ccmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -609,7 +632,7 @@ hexen2 fixme:
'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'
======================
*/
Expand Down Expand Up @@ -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')
Expand Down
35 changes: 31 additions & 4 deletions engine/server/sv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
Expand All @@ -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));
Expand All @@ -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))
Expand Down

0 comments on commit 1fe478d

Please sign in to comment.