From: bones_was_here Date: Thu, 8 Feb 2024 20:21:05 +0000 (+1000) Subject: server: always use correct case for map names X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=4223c283a73c5f2774a6e01515246dfc511889b7 server: always use correct case for map names Previously whatever was typed in as the map/changelevel argument was used even if it didn't match the case of the filename in the pak, which meant QC could see multiple instances of the same map that differed only by case, causing problems for gameplay stats. Now DP will always use the same case as the real .bsp filename for the `mapname` globals, and the sv_world* and cl_world* cvars, and the server status and getinfo/getstatus responses. This matches the behaviour of QC code which retrieved the name from the VFS, such as the `gotomap` and voting code in Nexuiz and Xonotic. Signed-off-by: bones_was_here --- diff --git a/fs.c b/fs.c index ad69946f..bea6cbcd 100644 --- a/fs.c +++ b/fs.c @@ -382,7 +382,7 @@ typedef struct pack_s char filename [MAX_OSPATH]; char shortname [MAX_QPATH]; filedesc_t handle; - int ignorecase; ///< PK3 ignores case + qbool ignorecase; ///< PK3 ignores case int numfiles; qbool vpack; qbool dlcache; @@ -412,7 +412,7 @@ void FS_Dir_f(cmd_state_t *cmd); void FS_Ls_f(cmd_state_t *cmd); void FS_Which_f(cmd_state_t *cmd); -static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet); +static searchpath_t *FS_FindFile (const char *name, int *index, const char **canonicalname, qbool quiet); static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack, fs_offset_t offset, fs_offset_t packsize, fs_offset_t realsize, int flags); @@ -1324,7 +1324,7 @@ qbool FS_AddPack(const char *pakfile, qbool *already_loaded, qbool keep_plain_di *already_loaded = false; // then find the real name... - search = FS_FindFile(pakfile, &index, true); + search = FS_FindFile(pakfile, &index, NULL, true); if(!search || search->pack) { Con_Printf("could not find pak \"%s\"\n", pakfile); @@ -2672,7 +2672,7 @@ Return the searchpath where the file was found (or NULL) and the file index in the package if relevant ==================== */ -static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet) +static searchpath_t *FS_FindFile (const char *name, int *index, const char **canonicalname, qbool quiet) { searchpath_t *search; pack_t *pak; @@ -2710,15 +2710,18 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet) if (index != NULL) *index = -1; + if (canonicalname) + *canonicalname = NULL; return NULL; } if (!quiet && developer_extra.integer) - Con_DPrintf("FS_FindFile: %s in %s\n", - pak->files[middle].name, pak->filename); + Con_DPrintf("FS_FindFile: %s in %s\n", pak->files[middle].name, pak->filename); if (index != NULL) *index = middle; + if (canonicalname) + *canonicalname = pak->files[middle].name; return search; } @@ -2740,6 +2743,8 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet) if (index != NULL) *index = -1; + if (canonicalname) + *canonicalname = name; return search; } } @@ -2750,6 +2755,8 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qbool quiet) if (index != NULL) *index = -1; + if (canonicalname) + *canonicalname = NULL; return NULL; } @@ -2766,7 +2773,7 @@ static qfile_t *FS_OpenReadFile (const char *filename, qbool quiet, qbool nonblo searchpath_t *search; int pack_ind; - search = FS_FindFile (filename, &pack_ind, quiet); + search = FS_FindFile (filename, &pack_ind, NULL, quiet); // Not found? if (search == NULL) @@ -3647,7 +3654,7 @@ int FS_FileType (const char *filename) searchpath_t *search; char fullpath[MAX_OSPATH]; - search = FS_FindFile (filename, NULL, true); + search = FS_FindFile (filename, NULL, NULL, true); if(!search) return FS_FILETYPE_NONE; @@ -3664,11 +3671,15 @@ int FS_FileType (const char *filename) FS_FileExists Look for a file in the packages and in the filesystem +Returns its canonical name (VFS path with correct capitalisation) if found, else NULL. +If the file is found outside a pak, this will be the same pointer as passed in. ================== */ -qbool FS_FileExists (const char *filename) +const char *FS_FileExists (const char *filename) { - return (FS_FindFile (filename, NULL, true) != NULL); + const char *canonicalname; + + return FS_FindFile(filename, NULL, &canonicalname, true) ? canonicalname : NULL; } @@ -4044,7 +4055,7 @@ void FS_Which_f(cmd_state_t *cmd) return; } filename = Cmd_Argv(cmd, 1); - sp = FS_FindFile(filename, &index, true); + sp = FS_FindFile(filename, &index, NULL, true); if (!sp) { Con_Printf("%s isn't anywhere\n", filename); return; @@ -4064,7 +4075,7 @@ void FS_Which_f(cmd_state_t *cmd) const char *FS_WhichPack(const char *filename) { int index; - searchpath_t *sp = FS_FindFile(filename, &index, true); + searchpath_t *sp = FS_FindFile(filename, &index, NULL, true); if(sp && sp->pack) return sp->pack->shortname; else if(sp) diff --git a/fs.h b/fs.h index 30b4487f..60658027 100644 --- a/fs.h +++ b/fs.h @@ -131,11 +131,17 @@ void FS_DefaultExtension (char *path, const char *extension, size_t size_path); #define FS_FILETYPE_NONE 0 #define FS_FILETYPE_FILE 1 #define FS_FILETYPE_DIRECTORY 2 -int FS_FileType (const char *filename); // the file can be into a package -int FS_SysFileType (const char *filename); // only look for files outside of packages - -qbool FS_FileExists (const char *filename); // the file can be into a package -qbool FS_SysFileExists (const char *filename); // only look for files outside of packages +/// Look for a file in the packages and in the filesystem +int FS_FileType (const char *filename); +/// Look for a file in the filesystem only +int FS_SysFileType (const char *filename); + +/// Look for a file in the packages and in the filesystem +/// Returns its canonical name (same case as used in the pack) if found, else NULL. +/// If the file is found outside a pak, this will be the same pointer as passed in. +const char *FS_FileExists (const char *filename); +/// Look for a file in the filesystem only +qbool FS_SysFileExists (const char *filename); unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflated_size, int level, mempool_t *mempool); unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflated_size, mempool_t *mempool); diff --git a/netconn.c b/netconn.c index b4dc5d50..0bc22f11 100644 --- a/netconn.c +++ b/netconn.c @@ -3677,7 +3677,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat LHNETADDRESS_ToString(LHNET_AddressFromSocket(mysocket), myaddressstring, sizeof(myaddressstring), true); MSG_WriteString(&sv_message, myaddressstring); MSG_WriteString(&sv_message, hostname.string); - MSG_WriteString(&sv_message, sv.name); + MSG_WriteString(&sv_message, sv.worldbasename); // How many clients are there? for (i = 0, numclients = 0;i < svs.maxclients;i++) if (svs.clients[i].active) diff --git a/server.h b/server.h index 22b6a1f8..a3e0436b 100644 --- a/server.h +++ b/server.h @@ -105,8 +105,6 @@ typedef struct server_s /// collision culling data world_t world; - /// map name - char name[64]; // %s followed by entrance name // variants of map name char worldbasename[MAX_QPATH]; // %s char worldname[MAX_QPATH]; // maps/%s.bsp diff --git a/sv_ccmds.c b/sv_ccmds.c index af283ddb..2b2a0c96 100644 --- a/sv_ccmds.c +++ b/sv_ccmds.c @@ -144,7 +144,7 @@ static void SV_Restart_f(cmd_state_t *cmd) if(host.hook.ToggleMenu) host.hook.ToggleMenu(); - dp_strlcpy(mapname, sv.name, sizeof(mapname)); + dp_strlcpy(mapname, sv.worldbasename, sizeof(mapname)); SV_SpawnServer(mapname); if(sv.active && host.hook.ConnectLocal != NULL) @@ -739,7 +739,7 @@ static void SV_Status_f(cmd_state_t *cmd) print ("host: %s\n", Cvar_VariableString (&cvars_all, "hostname", CF_SERVER)); print ("version: %s\n", engineversion); print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol)); - print ("map: %s\n", sv.name); + print ("map: %s\n", sv.worldbasename); print ("timing: %s\n", SV_TimingReport(vabuf, sizeof(vabuf))); print ("players: %i active (%i max)\n\n", players, svs.maxclients); diff --git a/sv_main.c b/sv_main.c index 2f2077a7..d2072e61 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1804,21 +1804,26 @@ void SV_SpawnServer (const char *map) char *entities; model_t *worldmodel; char modelname[sizeof(sv.worldname)]; + const char *canonicalname; char vabuf[1024]; Con_Printf("SpawnServer: %s\n", map); dpsnprintf (modelname, sizeof(modelname), "maps/%s.bsp", map); - if (!FS_FileExists(modelname)) + if (!(canonicalname = FS_FileExists(modelname))) { dpsnprintf (modelname, sizeof(modelname), "maps/%s", map); - if (!FS_FileExists(modelname)) + if (!(canonicalname = FS_FileExists(modelname))) { - Con_Printf("SpawnServer: no map file named %s\n", modelname); + Con_Printf(CON_ERROR "SpawnServer: no map file named %s.bsp\n", modelname); return; } } + // if it's not in a pak canonicalname will be the same pointer as modelname + // if it's in a pak canonicalname may differ by case + if (modelname != canonicalname) + dp_strlcpy(modelname, canonicalname, sizeof(modelname)); // SV_LockThreadMutex(); @@ -1839,7 +1844,7 @@ void SV_SpawnServer (const char *map) worldmodel = Mod_ForName(modelname, false, developer.integer > 0, NULL); if (!worldmodel || !worldmodel->TraceBox) { - Con_Printf("Couldn't load map %s\n", modelname); + Con_Printf(CON_ERROR "Couldn't load map %s\n", modelname); if(!host_isclient.integer) Sys_MakeProcessMean(); @@ -1928,10 +1933,10 @@ void SV_SpawnServer (const char *map) sv.active = true; // set level base name variables for later use - dp_strlcpy (sv.name, map, sizeof (sv.name)); dp_strlcpy(sv.worldname, modelname, sizeof(sv.worldname)); FS_StripExtension(sv.worldname, sv.worldnamenoextension, sizeof(sv.worldnamenoextension)); - dp_strlcpy(sv.worldbasename, !strncmp(sv.worldnamenoextension, "maps/", 5) ? sv.worldnamenoextension + 5 : sv.worldnamenoextension, sizeof(sv.worldbasename)); + dp_strlcpy(sv.worldbasename, !strncasecmp(sv.worldnamenoextension, "maps/", 5) ? sv.worldnamenoextension + 5 : sv.worldnamenoextension, sizeof(sv.worldbasename)); +// dp_strlcpy(sv.name, sv.worldbasename, sizeof (sv.name)); // TODO can we just remove this now? //Cvar_SetQuick(&sv_worldmessage, sv.worldmessage); // set later after QC is spawned Cvar_SetQuick(&sv_worldname, sv.worldname); Cvar_SetQuick(&sv_worldnamenoextension, sv.worldnamenoextension); @@ -1992,7 +1997,7 @@ void SV_SpawnServer (const char *map) sv.models[i+1] = Mod_ForName (sv.model_precache[i+1], false, false, sv.worldname); } if(i < sv.worldmodel->brush.numsubmodels) - Con_Printf("Too many submodels (MAX_MODELS is %i)\n", MAX_MODELS); + Con_Printf(CON_WARN "Too many submodels (MAX_MODELS is %i)\n", MAX_MODELS); // // load the rest of the entities @@ -2015,7 +2020,7 @@ void SV_SpawnServer (const char *map) else PRVM_serverglobalfloat(deathmatch) = deathmatch.integer; - PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(prog, sv.name); + PRVM_serverglobalstring(mapname) = PRVM_SetEngineString(prog, sv.worldbasename); // serverflags are for cross level information (sigils) PRVM_serverglobalfloat(serverflags) = svs.serverflags; diff --git a/sv_save.c b/sv_save.c index db8764fc..414e97a9 100644 --- a/sv_save.c +++ b/sv_save.c @@ -76,7 +76,7 @@ void SV_Savegame_to(prvm_prog_t *prog, const char *name) for (i=0 ; i