From 2df01316cee4053cd3b95e8b4ba1ed81135d48d9 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Tue, 13 Aug 2024 18:28:07 +0300 Subject: [PATCH] engine: client: add two new APIs for mainui to get extended new gameinfo structure --- common/gameinfo.h | 46 ++++++++++++++++++++++- engine/client/cl_gameui.c | 79 +++++++++++++++++++++++++++++++++------ engine/client/client.h | 5 ++- engine/menu_int.h | 4 ++ filesystem/filesystem.h | 9 +---- 5 files changed, 121 insertions(+), 22 deletions(-) diff --git a/common/gameinfo.h b/common/gameinfo.h index a53d9c2b..3b593f24 100644 --- a/common/gameinfo.h +++ b/common/gameinfo.h @@ -30,7 +30,7 @@ GAMEINFO stuff internal shared gameinfo structure (readonly for engine parts) ======================================================================== */ -typedef struct +typedef struct GAMEINFO_s { // filesystem info char gamefolder[64]; // used for change game '-game x' @@ -50,4 +50,48 @@ typedef struct int gamemode; } GAMEINFO; +/* +======================================================================== + +Extended GameInfo struct introduced in Xash3D FWGS + +GAMEINFO can't be reliably extended, as nor engine, nor menu can't be +sure about struct size. By adding struct versioning, we can check the +presense for extra fields. +======================================================================== +*/ + +#define GAMEINFO_VERSION 2 + +typedef enum gametype_e +{ + GAME_NORMAL, + GAME_SINGLEPLAYER_ONLY, + GAME_MULTIPLAYER_ONLY, +} gametype_t; + +typedef struct gameinfo2_s +{ + int gi_version; // should be set to desired struct version, e.g. GAMEINFO_VERSION + + // filesystem info + char gamefolder[64]; // used for change game + char startmap[64]; // map to start singleplayer game from + char trainmap[64]; // map to start hazardous course from (if specified) + char demomap[64]; // map to start demo chapter from (if specified) + char title[64]; // game title + char iconpath[64]; // path to game icon + char version[16]; // game version (optional) + uint32_t flags; // gameinfo flags, extended to fit more flags + + // mod info + char game_url[256]; // link to a developer's site + char update_url[256]; // link to updates page + char type[64]; // single, toolkit, multiplayer, etc + char date[64]; // release date + uint64_t size; // size in bytes + + gametype_t gamemode; +} gameinfo2_t; + #endif//GAMEINFO_H diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 39fa8f41..6b7c1c92 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -407,17 +407,21 @@ void Host_Credits( void ) gameui.dllFuncs.pfnFinalCredits(); } -static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in ) +static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in ) { + out->gi_version = GAMEINFO_VERSION; + Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder )); Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap )); Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap )); + Q_strncpy( out->demomap, in->demomap, sizeof( out->demomap )); Q_strncpy( out->title, in->title, sizeof( out->title )); Q_snprintf( out->version, sizeof( out->version ), "%g", in->version ); + Q_strncpy( out->iconpath, in->iconpath, sizeof( out->iconpath )); Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url )); Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url )); - Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size )); + out->size = in->size; Q_strncpy( out->type, in->type, sizeof( out->type )); Q_strncpy( out->date, in->date, sizeof( out->date )); @@ -435,6 +439,22 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in ) SetBits( out->flags, GFL_ANIMATED_TITLE ); } +static void UI_ToOldGameInfo( GAMEINFO *out, const gameinfo2_t *in ) +{ + Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder )); + Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap )); + Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap )); + Q_strncpy( out->title, in->title, sizeof( out->title )); + Q_strncpy( out->version, in->version, sizeof( out->version )); + out->flags = in->flags & 0xFFFF; + Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url )); + Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url )); + Q_strncpy( out->size, Q_memprint( in->size ), sizeof( out->size )); + Q_strncpy( out->type, in->type, sizeof( out->type )); + Q_strncpy( out->date, in->date, sizeof( out->date )); + out->gamemode = in->gamemode; +} + /* ==================== PIC_DrawGeneric @@ -932,11 +952,12 @@ pfnGetGameInfo ========= */ -static int GAME_EXPORT pfnGetGameInfo( GAMEINFO *pgameinfo ) +static int GAME_EXPORT pfnGetOldGameInfo( GAMEINFO *pgameinfo ) { - if( !pgameinfo ) return 0; + if( !pgameinfo ) + return 0; - *pgameinfo = gameui.gameInfo; + UI_ToOldGameInfo( pgameinfo, &gameui.gameInfo ); return 1; } @@ -948,8 +969,23 @@ pfnGetGamesList */ static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames ) { - if( numGames ) *numGames = FI->numgames; - return gameui.modsInfo; + if( numGames ) + *numGames = FI->numgames; + + if( !gameui.oldModsInfo ) + { + int i; + + // first allocate array of pointers + gameui.oldModsInfo = Mem_Calloc( gameui.mempool, sizeof( void* ) * FI->numgames ); + for( i = 0; i < FI->numgames; i++ ) + { + gameui.oldModsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO )); + UI_ToOldGameInfo( gameui.oldModsInfo[i], &gameui.modsInfo[i] ); + } + } + + return gameui.oldModsInfo; } /* @@ -1186,7 +1222,7 @@ static const ui_enginefuncs_t gEngfuncs = pfnKeyGetState, pfnMemAlloc, pfnMemFree, - pfnGetGameInfo, + pfnGetOldGameInfo, pfnGetGamesList, pfnGetFilesList, SV_GetSaveComment, @@ -1233,6 +1269,25 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i return COM_ParseFileSafe( data, buf, size, flags, len, NULL ); } +static gameinfo2_t *pfnGetGameInfo( int gi_version ) +{ + if( gi_version != gameui.gameInfo.gi_version ) + return NULL; + + return &gameui.gameInfo; +} + +static gameinfo2_t *pfnGetModInfo( int gi_version, int i ) +{ + if( i < 0 || i >= FI->numgames ) + return NULL; + + if( gi_version != gameui.modsInfo[i].gi_version ) + return NULL; + + return &gameui.modsInfo[i]; +} + static ui_extendedfuncs_t gExtendedfuncs = { pfnEnableTextInput, @@ -1246,6 +1301,8 @@ static ui_extendedfuncs_t gExtendedfuncs = NET_CompareAdrSort, Sys_GetNativeObject, &gNetApi, + pfnGetGameInfo, + pfnGetModInfo, }; void UI_UnloadProgs( void ) @@ -1367,11 +1424,9 @@ qboolean UI_LoadProgs( void ) Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" ); // setup gameinfo + gameui.modsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.modsInfo ) * FI->numgames ); for( i = 0; i < FI->numgames; i++ ) - { - gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO )); - UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] ); - } + UI_ConvertGameInfo( &gameui.modsInfo[i], FI->games[i] ); UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo diff --git a/engine/client/client.h b/engine/client/client.h index 06076292..4d97ab33 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -517,8 +517,9 @@ typedef struct player_info_t playerinfo; // local playerinfo gameui_draw_t ds; // draw2d stuff (menu images) - GAMEINFO gameInfo; // current gameInfo - GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI + gameinfo2_t gameInfo; // current gameInfo + gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand + GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand ui_globalvars_t *globals; diff --git a/engine/menu_int.h b/engine/menu_int.h index e15c1503..8dd840c4 100644 --- a/engine/menu_int.h +++ b/engine/menu_int.h @@ -218,6 +218,10 @@ typedef struct ui_extendedfuncs_s { int (*pfnCompareAdr)( const void *a, const void *b ); // netadr_t void *(*pfnGetNativeObject)( const char *name ); struct net_api_s *pNetAPI; + + // new mods info + gameinfo2_t *(*pfnGetGameInfo)( int gi_version ); // might return NULL if gi_version is unsupported + gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continiously call it until it returns null } ui_extendedfuncs_t; // deprecated export from old engine diff --git a/filesystem/filesystem.h b/filesystem/filesystem.h index 74bdda57..5e11cba2 100644 --- a/filesystem/filesystem.h +++ b/filesystem/filesystem.h @@ -25,6 +25,7 @@ GNU General Public License for more details. #include "xash3d_types.h" #include "const.h" #include "com_model.h" +#include "gameinfo.h" #ifdef __cplusplus extern "C" @@ -118,16 +119,10 @@ typedef struct gameinfo_s // HL25 compatibility keys qboolean hd_background; qboolean animated_title; + char demomap[MAX_QPATH]; } gameinfo_t; -typedef enum -{ - GAME_NORMAL, - GAME_SINGLEPLAYER_ONLY, - GAME_MULTIPLAYER_ONLY -} gametype_t; - typedef struct fs_dllinfo_t { char fullPath[2048]; // absolute disk path