]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
server: always use correct case for map names
authorbones_was_here <bones_was_here@xonotic.au>
Thu, 8 Feb 2024 20:21:05 +0000 (06:21 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Fri, 9 Feb 2024 07:14:46 +0000 (17:14 +1000)
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 <bones_was_here@xonotic.au>
fs.c
fs.h
netconn.c
server.h
sv_ccmds.c
sv_main.c
sv_save.c

diff --git a/fs.c b/fs.c
index ad69946f961894f4e474cab6b918beac2f8ef02e..bea6cbcd586ed9432ab0ebec6a8201a37254b4c5 100644 (file)
--- 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 30b4487f5706d62cc8f3f78c825c373c4d17c977..60658027810a4cbbaf1af5062c6607d7af39a8b6 100644 (file)
--- 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);
index b4dc5d5047afa454759d760846b0b854d11f7960..0bc22f11fc01a2315b5df2ab36edd727c874e770 100644 (file)
--- 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)
index 22b6a1f84f686e78320f11f99f5b996b70d715e5..a3e0436bbbfcba02c6cc4a2f20318c6cd89262e1 100644 (file)
--- 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
index af283ddbb595ef21fe4b79dfb301f0f8c4b25e3f..2b2a0c961ec8d54abdcaf0d8c52f786238be177a 100644 (file)
@@ -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);
 
index 2f2077a75abe544d523ab521cdae1f48e89db699..d2072e6139fa30eddc27b84e6c61881bed42f0a0 100644 (file)
--- 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;
index db8764fcce492f83d0669590de3ff8e46a7e4620..414e97a9b7a4716fee30f3bbc36cdb7a47cf1ee5 100644 (file)
--- 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<NUM_SPAWN_PARMS ; i++)
                        FS_Printf(f, "%f\n", svs.clients[0].spawn_parms[i]);
                FS_Printf(f, "%d\n", current_skill);
-               FS_Printf(f, "%s\n", sv.name);
+               FS_Printf(f, "%s\n", sv.worldbasename);
                FS_Printf(f, "%f\n",sv.time);
        }
        else