From: Mario Date: Thu, 16 Jul 2020 14:19:36 +0000 (+1000) Subject: Fix display of maps with missing previews, add a new option (enabled by default)... X-Git-Tag: xonotic-v0.8.6~328^2~24 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=86ab879e7839917047152b724f1f0722c434e268;p=xonotic%2Fxonotic-data.pk3dir.git Fix display of maps with missing previews, add a new option (enabled by default) which uses the .arena and .defi files directly instead of generating .mapinfo files, pull information from these files when generating .mapinfo, make use of the new search_packfile_begin extension to optimise .arena searches --- diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index 29538b621..1a0310218 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -9,6 +9,8 @@ #include #endif +bool autocvar_g_mapinfo_arena_compat = true; + #ifdef MENUQC #define WARN_COND false #else @@ -299,6 +301,22 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp mapMins = '0 0 0'; mapMaxs = '0 0 0'; + // try for a .arena or .defi file if no .mapinfo exists + bool isdefi = false; + string arena_fn = _MapInfo_FindArenaFile(pFilename, ".arena"); + int arena_fh = fopen(arena_fn, FILE_READ); + if(arena_fh < 0) + { + isdefi = true; + arena_fn = _MapInfo_FindArenaFile(pFilename, ".defi"); + 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)))) @@ -761,7 +779,7 @@ float MapInfo_isRedundant(string fn, string t) return false; } -bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi) +bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi, bool isgenerator) { // NOTE: .arena files can hold more than 1 map's information! // to handle this, we're going to store gathered information in local variables and save it if we encounter the correct map name @@ -809,10 +827,15 @@ 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; - FOREACH(Gametypes, it.m_flags & stored_supportedGametypes, + if(isgenerator) + MapInfo_Map_supportedGametypes = stored_supportedGametypes; + else { - _MapInfo_Map_ApplyGametype ("", pGametypeToSet, it, true); - }); + FOREACH(Gametypes, it.m_flags & stored_supportedGametypes, + { + _MapInfo_Map_ApplyGametype ("", pGametypeToSet, it, true); + }); + } return true; // no need to continue through the file, we have our map! } else @@ -898,20 +921,20 @@ string(string filename) whichpack = #503; #endif string _MapInfo_FindArenaFile(string pFilename, string extension) { - string base_pack = whichpack(strcat("maps/", pFilename, ".bsp")); string fallback = strcat("scripts/", pFilename, extension); + if(!checkextension("DP_QC_FS_SEARCH_PACKFILE")) + return fallback; + string base_pack = whichpack(strcat("maps/", pFilename, ".bsp")); if(base_pack == "") // this map isn't packaged! return fallback; - int glob = search_begin(strcat("scripts/*", extension), true, true); + int glob = search_packfile_begin(strcat("scripts/*", extension), true, true, base_pack); if(glob < 0) return fallback; int n = search_getsize(glob); for(int j = 0; j < n; ++j) { string file = search_getfilename(glob, j); - if(whichpack(file) != base_pack) - continue; // not in the same pk3! int fh = fopen(file, FILE_READ); if(fh < 0) @@ -967,21 +990,24 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet fh = fopen(fn, FILE_READ); if(fh < 0) { - bool isdefi = false; - // try for a .arena or .defi file if no .mapinfo exists - fn = _MapInfo_FindArenaFile(pFilename, ".arena"); - fh = fopen(fn, FILE_READ); - if(fh < 0) + if(autocvar_g_mapinfo_arena_compat) { - isdefi = true; - fn = _MapInfo_FindArenaFile(pFilename, ".defi"); + // try for .arena or .defi files if no .mapinfo exists + bool isdefi = false; + fn = _MapInfo_FindArenaFile(pFilename, ".arena"); fh = fopen(fn, FILE_READ); - } - if(fh >= 0) - { - _MapInfo_Map_Reset(); - if(_MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, isdefi)) - goto mapinfo_handled; // skip generation + if(fh < 0) + { + isdefi = true; + fn = _MapInfo_FindArenaFile(pFilename, ".defi"); + fh = fopen(fn, FILE_READ); + } + if(fh >= 0) + { + _MapInfo_Map_Reset(); + if(_MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, isdefi, false)) + goto mapinfo_handled; // skip generation + } } fn = strcat("maps/autogenerated/", pFilename, ".mapinfo"); diff --git a/qcsrc/common/mapinfo.qh b/qcsrc/common/mapinfo.qh index 9b4dfa257..43f5b30cf 100644 --- a/qcsrc/common/mapinfo.qh +++ b/qcsrc/common/mapinfo.qh @@ -673,6 +673,10 @@ void MapInfo_Cache_Destroy(); // disable caching void MapInfo_Cache_Create(); // enable caching void MapInfo_Cache_Invalidate(); // delete cache if any, but keep enabled +bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi, bool isgenerator); + +string _MapInfo_FindArenaFile(string pFilename, string extension); + void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, float recurse); void MapInfo_ClearTemps(); // call this when done with mapinfo for this frame diff --git a/qcsrc/dpdefs/upstream/menudefs.qc b/qcsrc/dpdefs/upstream/menudefs.qc index 36cedec4f..63d2c6388 100644 --- a/qcsrc/dpdefs/upstream/menudefs.qc +++ b/qcsrc/dpdefs/upstream/menudefs.qc @@ -159,7 +159,7 @@ float OS_MAC = 2; ////////////////////////////////////////////////// // AK FIXME: Create perhaps a special builtin file for the common cmds -void checkextension(string ext) = #1; +float checkextension(string ext) = #1; // error cmds void error(string err,...) = #2; @@ -542,7 +542,7 @@ void coverage() = #642; // Reports a coverage event. The engine counts for each //idea: Mario //darkplaces implementation: Mario //builtin definitions: -float(string pattern, float caseinsensitive, float quiet, string packfile) search_packfile_begin = #444; +float(string pattern, float caseinsensitive, float quiet, string packfile) search_packfile_begin = #74; //description: //extension to search_begin (DP_QC_FS_SEARCH), performs a filename search with the specified pattern (for example "maps/*.bsp") and stores the results in a search slot (minimum of 128 supported by any engine with this extension), the other functions take this returned search slot number, be sure to search_free when done (they are also freed on progs reload). //only searches for files within the specified packfile, which is expected to match the results of whichpack(). diff --git a/qcsrc/menu/draw.qc b/qcsrc/menu/draw.qc index ae6967e36..0bd4e29fe 100644 --- a/qcsrc/menu/draw.qc +++ b/qcsrc/menu/draw.qc @@ -83,6 +83,17 @@ vector draw_PictureSize(string pic) return drawgetimagesize(pic); } +bool draw_PictureExists(string pic) +{ + pic = draw_UseSkinFor(pic); + if (fexists(strcat(pic, ".tga"))) return true; + if (fexists(strcat(pic, ".png"))) return true; + if (fexists(strcat(pic, ".jpg"))) return true; + if (fexists(strcat(pic, ".pcx"))) return true; + + return false; +} + void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha) { drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0); diff --git a/qcsrc/menu/draw.qh b/qcsrc/menu/draw.qh index 69178cb03..611281913 100644 --- a/qcsrc/menu/draw.qh +++ b/qcsrc/menu/draw.qh @@ -21,6 +21,7 @@ void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize); void draw_Picture(vector origin, string pic, vector size, vector color, float alpha); vector draw_PictureSize(string pic); +bool draw_PictureExists(string pic); void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha); void draw_Text(vector origin, string text, vector size, vector color, float alpha, float allowColorCodes); void draw_CenterText(vector origin, string text, vector size, vector color, float alpha, float allowColorCodes); @@ -40,3 +41,4 @@ vector globalToBoxSize(vector v, vector scale); float draw_TextWidth_WithColors(string s, vector size); float draw_TextWidth_WithoutColors(string s, vector size); + diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc b/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc index 6e2d28297..57c2c61e6 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc @@ -17,14 +17,14 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, int i, entity mlb) strcpy(me.currentMapAuthor, strdecolorize(MapInfo_Map_author)); strcpy(me.currentMapDescription, MapInfo_Map_description); strcpy(me.currentMapPreviewImage, strcat("/maps/", MapInfo_Map_bspname)); - if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0') // Quake 3 compatibility + if(!draw_PictureExists(me.currentMapPreviewImage)) // Quake 3 compatibility strcpy(me.currentMapPreviewImage, strcat("/levelshots/", MapInfo_Map_bspname)); me.frame.setText(me.frame, me.currentMapBSPName); me.titleLabel.setText(me.titleLabel, me.currentMapTitle); me.authorLabel.setText(me.authorLabel, me.currentMapAuthor); me.descriptionLabel.setText(me.descriptionLabel, me.currentMapDescription); - if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0') + if(!draw_PictureExists(me.currentMapPreviewImage)) me.previewImage.src = "nopreview_map"; else me.previewImage.src = me.currentMapPreviewImage; diff --git a/qcsrc/menu/xonotic/maplist.qc b/qcsrc/menu/xonotic/maplist.qc index 73ce4616b..924924f01 100644 --- a/qcsrc/menu/xonotic/maplist.qc +++ b/qcsrc/menu/xonotic/maplist.qc @@ -157,7 +157,7 @@ void XonoticMapList_drawListBoxItem(entity me, int i, vector absSize, bool isSel if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0') { - if(draw_PictureSize(strcat("/levelshots/", MapInfo_Map_bspname)) == '0 0 0') + if(!draw_PictureExists(strcat("/levelshots/", MapInfo_Map_bspname))) draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); else draw_Picture(me.columnPreviewOrigin * eX, strcat("/levelshots/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha); diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index cc2b5e871..92353f6d1 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -882,10 +882,10 @@ spawnfunc(worldspawn) MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1); - if(fexists(strcat("scripts/", mapname, ".arena"))) + if(fexists(_MapInfo_FindArenaFile(mapname, ".arena"))) cvar_settemp("sv_q3acompat_machineshotgunswap", "1"); - if(fexists(strcat("scripts/", mapname, ".defi"))) + if(fexists(_MapInfo_FindArenaFile(mapname, ".defi"))) cvar_settemp("sv_q3defragcompat", "1"); // quake 3 music support diff --git a/xonotic-common.cfg b/xonotic-common.cfg index 88958889a..a0c4b679e 100644 --- a/xonotic-common.cfg +++ b/xonotic-common.cfg @@ -150,6 +150,8 @@ 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_arena_compat 1 "allow mapinfo data to be pulled directly from .arena and .defi files if they exist, rather than generating .mapinfo files based on their contents" + // load console command aliases and settings exec commands.cfg