From 5553db19ff97c03298790f3a32ff4b9012c6f4c2 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Mon, 25 Mar 2024 14:24:10 +1000 Subject: [PATCH] Add g_mapinfo_q3compat 3, support maps with .arena AND .defi files Fixes lack of CTS support on q3df maps that also have an invalid .arena file. Clarifies description and INFO logging. --- qcsrc/common/mapinfo.qc | 97 +++++++++++++++++++++-------------------- xonotic-common.cfg | 2 +- 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index df36ef1ca..92d275af4 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -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 == "") MapInfo_Map_titlestring = MapInfo_Map_bspname; else if(MapInfo_isRedundant(MapInfo_Map_bspname, MapInfo_Map_title)) diff --git a/xonotic-common.cfg b/xonotic-common.cfg index d8a1f1c20..d20a675c7 100644 --- a/xonotic-common.cfg +++ b/xonotic-common.cfg @@ -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 -- 2.39.2