]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
edict: fix escape parsing and make exceptions configurable
authorbones_was_here <bones_was_here@xonotic.au>
Sun, 4 Aug 2024 10:49:40 +0000 (20:49 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 5 Aug 2024 16:54:33 +0000 (02:54 +1000)
In 312123ecffc7e3dd892c7df754c911b47b9cdfaa a bug was introduced where
newlines were no longer supported in string fields.
This patch supports them again, which requires exceptions be
reintroduced to fully support some buggy maps, but this time there's a
cvar for documentation and adjustment.  The other notes and fixes in
https://github.com/DarkPlacesEngine/darkplaces/pull/185 still apply.

Signed-off-by: bones_was_here <bones_was_here@xonotic.au>
prvm_edict.c

index d4a2120f2075970fb7361114ea3965c8f118eec9..cc318e9914a01b585ab6158c84462c0c26f504e2 100644 (file)
@@ -53,6 +53,7 @@ cvar_t prvm_garbagecollection_notify = {CF_CLIENT | CF_SERVER, "prvm_garbagecoll
 cvar_t prvm_garbagecollection_scan_limit = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_scan_limit", "50000", "scan this many fields or resources per second to free up unreferenced resources"};
 cvar_t prvm_garbagecollection_strings = {CF_CLIENT | CF_SERVER, "prvm_garbagecollection_strings", "1", "automatically call strunzone() on strings that are not referenced"};
 cvar_t prvm_stringdebug = {CF_CLIENT | CF_SERVER, "prvm_stringdebug", "0", "Print debug and warning messages related to strings"};
+cvar_t sv_entfields_noescapes = {CF_SERVER, "sv_entfields_noescapes", "wad", "Space-separated list of fields in which backslashes won't be parsed as escapes when loading entities from .bsp or .ent files. This is a workaround for buggy maps with unescaped backslashes used as path separators (only forward slashes are allowed in Quake VFS paths)."};
 
 static double prvm_reuseedicts_always_allow = 0;
 qbool prvm_runawaycheck = true;
@@ -1280,12 +1281,11 @@ const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_
 {
        mdef_t *key;
        qbool anglehack;
-       qbool init;
+       qbool init = false;
+       qbool parsebackslash = true;
        char keyname[256];
        size_t n;
 
-       init = false;
-
 // go through all the dictionary pairs
        while (1)
        {
@@ -1311,20 +1311,35 @@ const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_
                if (!strcmp(com_token, "light"))
                        dp_strlcpy (com_token, "light_lev", sizeof(com_token)); // hack for single light def
 
-               dp_strlcpy (keyname, com_token, sizeof(keyname));
+               n = dp_strlcpy (keyname, com_token, sizeof(keyname));
 
                // another hack to fix keynames with trailing spaces
-               n = strlen(keyname);
                while (n && keyname[n-1] == ' ')
                {
                        keyname[n-1] = 0;
                        n--;
                }
 
+       // Check if escape parsing is disabled for this key (see cvar description).
+       // Escapes are always used in savegames and DP_QC_ENTITYSTRING for compatibility.
+               if (!saveload)
+               {
+                       const char *cvarpos = sv_entfields_noescapes.string;
+
+                       while (COM_ParseToken_Console(&cvarpos))
+                       {
+                               if (strcmp(com_token, keyname) == 0)
+                               {
+                                       parsebackslash = false;
+                                       break;
+                               }
+                       }
+               }
+
        // parse value
                // If loading a save, unescape characters (they're escaped when saving).
                // Otherwise, load them as they are (BSP compilers don't support escaping).
-               if (!COM_ParseToken_Simple(&data, false, saveload, true))
+               if (!COM_ParseToken_Simple(&data, false, parsebackslash, true))
                        prog->error_cmd("PRVM_ED_ParseEdict: EOF without closing brace");
                if (developer_entityparsing.integer)
                        Con_Printf(" \"%s\"\n", com_token);
@@ -1361,7 +1376,8 @@ const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_
                        prog->error_cmd("PRVM_ED_ParseEdict: parse error");
        }
 
-       if (!init) {
+       if (!init)
+       {
                ent->free = true;
                ent->freetime = host.realtime;
        }
@@ -3191,6 +3207,7 @@ void PRVM_Init (void)
        Cvar_RegisterVariable (&prvm_garbagecollection_scan_limit);
        Cvar_RegisterVariable (&prvm_garbagecollection_strings);
        Cvar_RegisterVariable (&prvm_stringdebug);
+       Cvar_RegisterVariable (&sv_entfields_noescapes);
 
        // COMMANDLINEOPTION: PRVM: -norunaway disables the runaway loop check (it might be impossible to exit DarkPlaces if used!)
        prvm_runawaycheck = !Sys_CheckParm("-norunaway");