]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add g_mapinfo_q3compat 3, support maps with .arena AND .defi files
authorbones_was_here <bones_was_here@xonotic.au>
Mon, 25 Mar 2024 04:24:10 +0000 (14:24 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Fri, 29 Mar 2024 09:19:22 +0000 (19:19 +1000)
Fixes lack of CTS support on q3df maps that also have an invalid .arena
file.
Clarifies description and INFO logging.

qcsrc/common/mapinfo.qc
xonotic-common.cfg

index df36ef1ca6fb94e3da0b443e73fe9fcecaeb0ef2..92d275af443576178b443790d87bbb7ab1380e71 100644 (file)
@@ -274,9 +274,30 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        float diameter, spawnpoints;
        float spawnplaces;
        bool is_q3df_map = false;
-
        vector mapMins, mapMaxs;
 
+       if(autocvar_g_mapinfo_q3compat >= 2) // generate mapinfo using arena data
+       {
+               // try for .arena or .defi files, as they may have more accurate information
+               // supporting .arena AND .defi for the same map
+               bool success = false;
+               fh = -1;
+               fn = _MapInfo_FindArenaFile(pFilename, ".arena");
+               if(fn != "" && (fh = fopen(fn, FILE_READ)) >= 0)
+               {
+                       success = _MapInfo_ParseArena(fn, fh, pFilename, NULL, false, true);
+                       fclose(fh);
+               }
+               fn = _MapInfo_FindArenaFile(pFilename, ".defi");
+               if(fn != "" && (fh = fopen(fn, FILE_READ)) >= 0)
+               {
+                       success |= _MapInfo_ParseArena(fn, fh, pFilename, NULL, true, true);
+                       fclose(fh);
+               }
+               if (success && autocvar_g_mapinfo_q3compat == 3)
+                       return 3; // skip entity analysis
+       }
+
        r = 1;
        fn = strcat("maps/", pFilename, ".ent");
        fh = fopen(fn, FILE_READ);
@@ -288,39 +309,15 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        }
        if(fh < 0)
                return 0;
-       LOG_INFO("Analyzing ", fn, " to generate initial mapinfo");
+       LOG_INFO("Generating ", pFilename, ".mapinfo: analyzing ", fn);
 
        inWorldspawn = 2;
-       MapInfo_Map_flags = 0;
-       MapInfo_Map_supportedGametypes = 0;
        spawnpoints = 0;
        spawnplaces = 0;
        _MapInfo_Map_worldspawn_music = "";
        mapMins = '0 0 0';
        mapMaxs = '0 0 0';
 
-       if(autocvar_g_mapinfo_q3compat == 2) // generate mapinfo using arena data
-       {
-               // try for .arena or .defi files, as they may have more accurate information
-               bool isdefi = false;
-               float arena_fh = -1;
-               string arena_fn = _MapInfo_FindArenaFile(pFilename, ".arena");
-               if(arena_fn != "")
-                       arena_fh = fopen(arena_fn, FILE_READ);
-               if(arena_fh < 0)
-               {
-                       isdefi = true;
-                       arena_fn = _MapInfo_FindArenaFile(pFilename, ".defi");
-                       if(arena_fn != "")
-                               arena_fh = fopen(arena_fn, FILE_READ);
-               }
-               if(arena_fh >= 0)
-               {
-                       _MapInfo_ParseArena(arena_fn, arena_fh, pFilename, NULL, isdefi, true);
-                       fclose(arena_fh);
-               }
-       }
-
        for (;;)
        {
                if (!((s = fgets(fh))))
@@ -396,7 +393,7 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
                                else if(v == "target_music" || v == "trigger_music")
                                        _MapInfo_Map_worldspawn_music = string_null; // don't use regular BGM
                                else if(v == "target_stopTimer")
-                                       is_q3df_map = true; // don't support standard gamemodes
+                                       is_q3df_map = true; // don't support standard gametypes UNLESS we found them in .arena
                                else
                                        FOREACH(Gametypes, true, it.m_generate_mapinfo(it, v));
                        }
@@ -803,6 +800,10 @@ bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gamety
        int stored_supportedFeatures = 0;
        int stored_flags = 0;
        string t, s;
+
+       if (isgenerator)
+               LOG_INFO("Generating ", pFilename, ".mapinfo: analyzing ", arena_filename);
+
        for (;;)
        {
                if (!((s = fgets(fh))))
@@ -836,8 +837,9 @@ bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gamety
                                if(stored_Map_title != "")
                                        MapInfo_Map_title = stored_Map_title;
                                MapInfo_Map_author = stored_Map_author;
+                               // might have .arena AND .defi for the same map so these bitfields are OR'd
                                if(isgenerator)
-                                       MapInfo_Map_supportedGametypes = stored_supportedGametypes;
+                                       MapInfo_Map_supportedGametypes |= stored_supportedGametypes;
                                else
                                {
                                        FOREACH(Gametypes, it.m_flags & stored_supportedGametypes,
@@ -845,8 +847,8 @@ bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gamety
                                                _MapInfo_Map_ApplyGametype ("", pGametypeToSet, it, true);
                                        });
                                }
-                               MapInfo_Map_supportedFeatures = stored_supportedFeatures;
-                               MapInfo_Map_flags = stored_flags;
+                               MapInfo_Map_supportedFeatures |= stored_supportedFeatures;
+                               MapInfo_Map_flags |= stored_flags;
                                return true; // no need to continue through the file, we have our map!
                        }
                        else
@@ -1024,28 +1026,27 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
        fh = fopen(fn, FILE_READ);
        if(fh < 0)
        {
-               if(autocvar_g_mapinfo_q3compat) // use arena data instead of generating a mapinfo file
+               if(autocvar_g_mapinfo_q3compat == 1) // use arena data instead of generating a mapinfo file
                {
-                       bool isdefi = false;
-                       if(autocvar_g_mapinfo_q3compat == 1) // only parse .arena files in mode 1
-                       {
-                               fn = _MapInfo_FindArenaFile(pFilename, ".arena");
-                               if(fn != "")
-                                       fh = fopen(fn, FILE_READ);
-                       }
-                       if(fh < 0 || autocvar_g_mapinfo_q3compat == 2)
+                       // supporting .arena AND .defi for the same map
+                       bool success = false;
+                       fn = _MapInfo_FindArenaFile(pFilename, ".arena");
+                       if(fn != "" && (fh = fopen(fn, FILE_READ)) >= 0)
                        {
-                               isdefi = true;
-                               fn = _MapInfo_FindArenaFile(pFilename, ".defi");
-                               if(fn != "")
-                                       fh = fopen(fn, FILE_READ);
+                               _MapInfo_Map_Reset();
+                               success = _MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, false, false);
+                               fclose(fh);
                        }
-                       if(fh >= 0)
+                       fn = _MapInfo_FindArenaFile(pFilename, ".defi");
+                       if(fn != "" && (fh = fopen(fn, FILE_READ)) >= 0)
                        {
-                               _MapInfo_Map_Reset();
-                               if(_MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, isdefi, false))
-                                       goto mapinfo_handled; // skip generation
+                               if(!success)
+                                       _MapInfo_Map_Reset();
+                               success |= _MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, true, false);
+                               fclose(fh);
                        }
+                       if(success)
+                               goto mapinfo_handled; // skip generation
                }
 
                fn = strcat("maps/autogenerated/", pFilename, ".mapinfo");
@@ -1306,9 +1307,9 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                else if(WARN_COND)
                        LOG_WARN("Map ", pFilename, " provides unknown info item ", t, ", ignored");
        }
-       LABEL(mapinfo_handled)
        fclose(fh);
 
+LABEL(mapinfo_handled)
        if(MapInfo_Map_title == "<TITLE>")
                MapInfo_Map_titlestring = MapInfo_Map_bspname;
        else if(MapInfo_isRedundant(MapInfo_Map_bspname, MapInfo_Map_title))
index d8a1f1c20b2ba84ffb5ccbb9682a591d341ab0f0..d20a675c7cfc9c42e2ef1d561ca0ad0ed6151fb3 100644 (file)
@@ -154,7 +154,7 @@ set debug_deglobalization_clear 0 "make the new wrappers set globals to NaN afte
 // disabling until it's complete
 set prvm_garbagecollection_enable 0
 
-set g_mapinfo_q3compat 1 "0: generate .mapinfo if none exists, ignoring .arena and .defi files. 1: read .arena and .defi files, don't generate .mapinfo. 2: generate .mapinfo if none exists using data from .arena files instead of reading them, .defi files continue to be used directly"
+set g_mapinfo_q3compat 1 "If no .mapinfo file exists:: 0: generate .mapinfo using entities only. 1: read .arena and .defi files directly, don't generate .mapinfo. 2: generate .mapinfo using .arena and .defi files, and entities. 3: generate .mapinfo using .arena and .defi files only."
 
 // load console command aliases and settings
 exec commands.cfg