From 674a4e5883b9f509cde6a197c1d606894e185c22 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 5 Feb 2025 18:22:48 +0300 Subject: [PATCH] filesystem: add ability to mount HD, LV, addon and language folders by engine request --- engine/client/cl_main.c | 2 +- engine/common/common.h | 1 + engine/common/filesystem_engine.c | 4 +-- filesystem/filesystem.c | 57 ++++++++++++++++++++++++------- filesystem/filesystem.h | 7 +++- filesystem/filesystem_internal.h | 2 +- 6 files changed, 56 insertions(+), 17 deletions(-) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 7b0e54dc..e8c6fb84 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3148,7 +3148,7 @@ qboolean CL_PrecacheResources( void ) // if we downloaded new WAD files or any other archives they must be added to searchpath if( CL_ShouldRescanFilesystem( )) - g_fsapi.Rescan(); + FS_Rescan_f(); // NOTE: world need to be loaded as first model for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext ) diff --git a/engine/common/common.h b/engine/common/common.h index 60eecbca..754bb79c 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -410,6 +410,7 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; +void FS_Rescan_f( void ); // // cmd.c diff --git a/engine/common/filesystem_engine.c b/engine/common/filesystem_engine.c index 71c9c468..128f1ab9 100644 --- a/engine/common/filesystem_engine.c +++ b/engine/common/filesystem_engine.c @@ -69,9 +69,9 @@ void *FS_GetNativeObject( const char *obj ) return NULL; } -static void FS_Rescan_f( void ) +void FS_Rescan_f( void ) { - FS_Rescan(); + FS_Rescan( 0, NULL ); } static void FS_ClearPaths_f( void ) diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index a0e9c306..6b9e723a 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -59,8 +59,9 @@ char fs_rootdir[MAX_SYSPATH]; searchpath_t *fs_writepath; static searchpath_t *fs_searchpaths = NULL; // chain -static char fs_basedir[MAX_SYSPATH]; // base game directory -static char fs_gamedir[MAX_SYSPATH]; // game current directory +static char fs_basedir[MAX_SYSPATH]; // base game directory +static char fs_gamedir[MAX_SYSPATH]; // game current directory +static string fs_language; // add archives in specific order PAK -> PK3 -> WAD // so raw WADs takes precedence over WADs included into PAKs and PK3s @@ -1249,14 +1250,39 @@ void FS_AddGameHierarchy( const char *dir, uint flags ) if( isGameDir ) { Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_DOWNLOADED_DIRECTORY, dir ); - FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH ); + FS_AddGameDirectory( buf, FS_NOWRITE_PATH|FS_CUSTOM_PATH ); } Q_snprintf( buf, sizeof( buf ), "%s/", dir ); FS_AddGameDirectory( buf, flags ); + + if( FBitSet( flags, FS_MOUNT_HD )) + { + Q_snprintf( buf, sizeof( buf ), "%s_hd/", dir ); + FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH ); + } + + if( FBitSet( flags, FS_MOUNT_ADDON )) + { + Q_snprintf( buf, sizeof( buf ), "%s_addon/", dir ); + FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH ); + } + + if( FBitSet( flags, FS_MOUNT_LV )) + { + Q_snprintf( buf, sizeof( buf ), "%s_lv/", dir ); + FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH ); + } + + if( FBitSet( flags, FS_MOUNT_L10N ) && COM_CheckStringEmpty( fs_language ) && Q_isalpha( fs_language )) + { + Q_snprintf( buf, sizeof( buf ), "%s_%s/", dir, fs_language ); + FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH ); + } + if( isGameDir ) { Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_CUSTOM_DIRECTORY, dir ); - FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH ); + FS_AddGameDirectory( buf, FS_NOWRITE_PATH|FS_CUSTOM_PATH ); } } @@ -1265,29 +1291,35 @@ void FS_AddGameHierarchy( const char *dir, uint flags ) FS_Rescan ================ */ -void FS_Rescan( void ) +void FS_Rescan( uint32_t flags, const char *language ) { const char *str; - const int extrasFlags = FS_NOWRITE_PATH | FS_CUSTOM_PATH; Con_Reportf( "%s( %s )\n", __func__, GI->title ); FS_ClearSearchPath(); + flags &= FS_MOUNT_HD|FS_MOUNT_LV|FS_MOUNT_ADDON|FS_MOUNT_L10N; + + if( FBitSet( flags, FS_MOUNT_L10N )) + Q_strncpy( fs_language, language, sizeof( fs_language )); + else + fs_language[0] = 0; + str = getenv( "XASH3D_EXTRAS_PAK1" ); if( COM_CheckString( str )) - FS_MountArchive_Fullpath( str, extrasFlags ); + FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH ); str = getenv( "XASH3D_EXTRAS_PAK2" ); if( COM_CheckString( str )) - FS_MountArchive_Fullpath( str, extrasFlags ); + FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH ); if( Q_stricmp( GI->basedir, GI->gamefolder )) - FS_AddGameHierarchy( GI->basedir, 0 ); + FS_AddGameHierarchy( GI->basedir, flags ); if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir )) - FS_AddGameHierarchy( GI->falldir, 0 ); + FS_AddGameHierarchy( GI->falldir, flags ); GI->added = true; - FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH ); + FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH | flags ); } /* @@ -1332,7 +1364,7 @@ void FS_LoadGameInfo( const char *rootfolder ) FS_CreatePath( buf ); } - FS_Rescan(); // create new filesystem + FS_Rescan( 0, NULL ); // create new filesystem } /* @@ -1575,6 +1607,7 @@ qboolean FS_InitStdio( qboolean unused_set_to_true, const char *rootdir, const c Q_strncpy( fs_gamedir, gamedir, sizeof( fs_gamedir )); Q_strncpy( fs_basedir, basedir, sizeof( fs_basedir )); Q_strncpy( fs_rodir, rodir, sizeof( fs_rodir )); + fs_language[0] = 0; // validate user input if( COM_CheckStringEmpty( fs_rodir ) && !Q_stricmp( fs_rodir, fs_rootdir )) diff --git a/filesystem/filesystem.h b/filesystem/filesystem.h index a0feff41..2de28919 100644 --- a/filesystem/filesystem.h +++ b/filesystem/filesystem.h @@ -48,6 +48,11 @@ enum FS_SKIP_ARCHIVED_WADS = BIT( 5 ), // don't mount wads inside archives automatically FS_LOAD_PACKED_WAD = BIT( 6 ), // this wad is packed inside other archive + FS_MOUNT_HD = BIT( 7 ), // mount high definition content folder + FS_MOUNT_LV = BIT( 8 ), // mount low violence content folder + FS_MOUNT_ADDON = BIT( 9 ), // mount addon folder + FS_MOUNT_L10N = BIT( 10 ), // mount localization folder + FS_GAMEDIRONLY_SEARCH_FLAGS = FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH }; @@ -151,7 +156,7 @@ typedef struct fs_api_t void (*ShutdownStdio)( void ); // search path utils - void (*Rescan)( void ); + void (*Rescan)( uint32_t flags, const char *language ); void (*ClearSearchPath)( void ); void (*AllowDirectPaths)( qboolean enable ); void (*AddGameDirectory)( const char *dir, uint flags ); diff --git a/filesystem/filesystem_internal.h b/filesystem/filesystem_internal.h index f8b28902..ce717747 100644 --- a/filesystem/filesystem_internal.h +++ b/filesystem/filesystem_internal.h @@ -167,7 +167,7 @@ void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; // search path utils -void FS_Rescan( void ); +void FS_Rescan( uint32_t flags, const char *language ); void FS_ClearSearchPath( void ); void FS_AllowDirectPaths( qboolean enable ); void FS_AddGameDirectory( const char *dir, uint flags );