mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
engine: introduce vfs.cfg to properly control user set addon folders
vfs.cfg executed before game directory is mounted, this way we can know which folders must be mounted before engine initialization. This commit also removes buggy hot reload of the addon folders.
This commit is contained in:
16
Documentation/extensions/addon-folders.md
Normal file
16
Documentation/extensions/addon-folders.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Addon folders in Xash3D FWGS
|
||||
|
||||
Xash3D FWGS supports both GoldSource-style addon folders and has few own. Each directory can have it's own archives that will be mounted with lower priority than directory itself.
|
||||
|
||||
Below is the mounts map, in order of precedence from least important to most important.
|
||||
|
||||
|--------------------|------|
|
||||
| Directory | Note |
|
||||
|--------------------|------|
|
||||
| `$game/downloaded` | Always added. Used to store server downloads.|
|
||||
| `$game` | This is the game directory. |
|
||||
| `$game/custom` | Always added. Used for user modifications content. |
|
||||
| `$game_hd` | Added with `fs_mount_hd` set to non-zero value. Used for high definition content, similar to GoldSrc.. |
|
||||
| `$game_addon` | Added with `fs_mount_addon` set to non-zero value. Used for user modifications content, similar to GoldSrc. |
|
||||
| `$game_lv` | Added with `fs_mount_lv` set to non-zero value. Used for low-violence content, similar to GoldSrc. |
|
||||
| `$game_$language` | Added with `fs_mount_l10n` set to non-zero value. Language is controlled with `ui_language` cvar or `-language` command line switch. Used for localization content, similar to GoldSrc. |
|
||||
@@ -3127,9 +3127,6 @@ static qboolean CL_ShouldRescanFilesystem( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( FBitSet( fs_mount_lv.flags|fs_mount_hd.flags|fs_mount_addon.flags|fs_mount_l10n.flags|ui_language.flags, FCVAR_CHANGED ))
|
||||
retval = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,11 +167,6 @@ extern convar_t cl_filterstuffcmd;
|
||||
extern convar_t rcon_password;
|
||||
extern convar_t hpk_custom_file;
|
||||
extern convar_t con_gamemaps;
|
||||
extern convar_t fs_mount_lv;
|
||||
extern convar_t fs_mount_hd;
|
||||
extern convar_t fs_mount_addon;
|
||||
extern convar_t fs_mount_l10n;
|
||||
extern convar_t ui_language; // historically used for UI, but now controls mounted localization directory
|
||||
|
||||
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
|
||||
|
||||
@@ -416,7 +411,8 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
void FS_Rescan_f( void );
|
||||
void FS_CheckConfig( void );
|
||||
void FS_LoadGameInfo( void );
|
||||
void FS_SaveVFSConfig( void );
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
@@ -687,6 +683,8 @@ void pfnResetTutorMessageDecayData( void );
|
||||
void Con_CompleteCommand( field_t *field );
|
||||
void Cmd_AutoComplete( char *complete_string );
|
||||
void Cmd_AutoCompleteClear( void );
|
||||
void Host_InitializeConfig( file_t *f, const char *config, const char *description );
|
||||
void Host_FinalizeConfig( file_t *f, const char *config );
|
||||
|
||||
//
|
||||
// custom.c
|
||||
|
||||
@@ -1403,8 +1403,15 @@ static void Cmd_WriteOpenGLVariables( file_t *f )
|
||||
Cvar_LookupVars( FCVAR_GLCONFIG, NULL, f, (setpair_t)Cmd_WriteOpenGLCvar );
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
static void Host_FinalizeConfig( file_t *f, const char *config )
|
||||
void Host_InitializeConfig( file_t *f, const char *config, const char *description )
|
||||
{
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\t%s - %s\n", config, description );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
}
|
||||
|
||||
void Host_FinalizeConfig( file_t *f, const char *config )
|
||||
{
|
||||
string backup, newcfg;
|
||||
|
||||
@@ -1418,6 +1425,8 @@ static void Host_FinalizeConfig( file_t *f, const char *config )
|
||||
FS_Rename( newcfg, config );
|
||||
}
|
||||
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
===============
|
||||
Host_WriteConfig
|
||||
@@ -1438,10 +1447,7 @@ void Host_WriteConfig( void )
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tconfig.cfg - archive of cvars\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Host_InitializeConfig( f, "config.cfg", "archive of cvars" );
|
||||
Key_WriteBindings( f );
|
||||
Cvar_WriteVariables( f, FCVAR_ARCHIVE );
|
||||
Info_WriteVars( f );
|
||||
@@ -1465,6 +1471,8 @@ void Host_WriteConfig( void )
|
||||
else Con_DPrintf( S_ERROR "Couldn't write config.cfg.\n" );
|
||||
|
||||
NET_SaveMasters();
|
||||
|
||||
FS_SaveVFSConfig();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1486,10 +1494,7 @@ void GAME_EXPORT Host_WriteServerConfig( const char *name )
|
||||
|
||||
if(( f = FS_Open( newconfigfile, "w", false )) != NULL )
|
||||
{
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Host_InitializeConfig( f, "game.cfg", "multiplayer server temporary config" );
|
||||
|
||||
Cvar_WriteVariables( f, FCVAR_SERVER );
|
||||
CSCR_WriteGameCVars( f, "settings.scr" );
|
||||
@@ -1521,11 +1526,7 @@ void Host_WriteOpenGLConfig( void )
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\t%s - archive of renderer implementation cvars\n", name );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\n" );
|
||||
Host_InitializeConfig( f, name, "archive of renderer implementation cvars" );
|
||||
Cmd_WriteOpenGLVariables( f );
|
||||
|
||||
Host_FinalizeConfig( f, name );
|
||||
@@ -1551,10 +1552,7 @@ void Host_WriteVideoConfig( void )
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Host_InitializeConfig( f, "video.cfg", "archive of renderer variables" );
|
||||
Cvar_WriteVariables( f, FCVAR_RENDERINFO );
|
||||
Host_FinalizeConfig( f, "video.cfg" );
|
||||
}
|
||||
@@ -1577,11 +1575,7 @@ void Key_EnumCmds_f( void )
|
||||
f = FS_Open( "../help.txt", "w", false );
|
||||
if( f )
|
||||
{
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\thelp.txt - xash commands and console variables\n");
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
|
||||
Host_InitializeConfig( f, "help.txt", "xash commands and console variables" );
|
||||
FS_Printf( f, "\n\n\t\t\tconsole variables\n\n");
|
||||
Cvar_LookupVars( 0, NULL, f, (setpair_t)Cmd_WriteHelp );
|
||||
FS_Printf( f, "\n\n\t\t\tconsole commands\n\n");
|
||||
|
||||
@@ -27,11 +27,11 @@ GNU General Public License for more details.
|
||||
#include "library.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount high definition content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount low violence models content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount addon content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount localization content folder" );
|
||||
CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "selected game language" );
|
||||
static CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_PRIVILEGED, "mount high definition content folder" );
|
||||
static CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_PRIVILEGED, "mount low violence models content folder" );
|
||||
static CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_PRIVILEGED, "mount addon content folder" );
|
||||
static CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_PRIVILEGED, "mount localization content folder" );
|
||||
static CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_PRIVILEGED, "selected game language" );
|
||||
|
||||
fs_api_t g_fsapi;
|
||||
fs_globals_t *FI;
|
||||
@@ -81,7 +81,7 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FS_Rescan_f( void )
|
||||
static uint32_t FS_MountFlags( void )
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
@@ -91,15 +91,76 @@ void FS_Rescan_f( void )
|
||||
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
|
||||
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
|
||||
|
||||
g_fsapi.Rescan( flags, ui_language.string );
|
||||
return flags;
|
||||
}
|
||||
|
||||
void FS_Rescan_f( void )
|
||||
{
|
||||
g_fsapi.Rescan( FS_MountFlags(), ui_language.string );
|
||||
}
|
||||
|
||||
static void FS_LoadVFSConfig( const char *gamedir )
|
||||
{
|
||||
string parm;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
return;
|
||||
|
||||
Cbuf_AddTextf( "exec %s/vfs.cfg\n", gamedir );
|
||||
Cbuf_Execute();
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-language", parm ))
|
||||
{
|
||||
Cvar_DirectSet( &ui_language, parm );
|
||||
Cvar_DirectSet( &fs_mount_l10n, "1" );
|
||||
}
|
||||
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( ui_language.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
void FS_SaveVFSConfig( void )
|
||||
{
|
||||
file_t *f;
|
||||
|
||||
if( !FBitSet( fs_mount_hd.flags|fs_mount_lv.flags|fs_mount_l10n.flags|fs_mount_addon.flags|ui_language.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
Con_Reportf( "%s: no need to save vfs.cfg\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
f = FS_Open( "vfs.cfg.new", "w", true );
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: couldn't open vfs.cfg for write\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
FS_Printf( f, "%s \"%d\"\n", fs_mount_hd.name, (int)fs_mount_hd.value );
|
||||
FS_Printf( f, "%s \"%d\"\n", fs_mount_lv.name, (int)fs_mount_lv.value );
|
||||
FS_Printf( f, "%s \"%d\"\n", fs_mount_l10n.name, (int)fs_mount_l10n.value );
|
||||
FS_Printf( f, "%s \"%d\"\n", fs_mount_addon.name, (int)fs_mount_addon.value );
|
||||
FS_Printf( f, "%s \"%s\"\n", ui_language.name, ui_language.string );
|
||||
|
||||
Host_FinalizeConfig( f, "vfs.cfg" );
|
||||
|
||||
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( ui_language.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
void FS_LoadGameInfo( void )
|
||||
{
|
||||
FS_LoadVFSConfig( g_fsapi.Gamedir( ));
|
||||
|
||||
g_fsapi.LoadGameInfo( FS_MountFlags(), ui_language.string );
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
{
|
||||
FS_ClearSearchPath();
|
||||
@@ -196,10 +257,7 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
|
||||
return true;
|
||||
}
|
||||
|
||||
#if XASH_EMSCRIPTEN
|
||||
Q_strncpy( out, "/rwdir", size );
|
||||
return true;
|
||||
#elif TARGET_OS_IOS
|
||||
#if TARGET_OS_IOS
|
||||
Q_strncpy( out, IOS_GetDocsDir(), size );
|
||||
return true;
|
||||
#elif XASH_ANDROID && XASH_SDL
|
||||
@@ -264,20 +322,9 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return true;
|
||||
}
|
||||
|
||||
#if XASH_EMSCRIPTEN
|
||||
Q_strncpy( out, "/rodir", size );
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_CheckConfig( void )
|
||||
{
|
||||
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value )
|
||||
FS_Rescan_f();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
|
||||
@@ -148,6 +148,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
O("-bugcomp [opts] ", "enable precise bug compatibility")
|
||||
O(" ", "will break games that don't require it")
|
||||
O(" ", "refer to engine documentation for more info")
|
||||
O("-language <lang> ", "mount localization game directory")
|
||||
O("-disablehelp ", "disable this message")
|
||||
#if !XASH_DEDICATED
|
||||
O("-dedicated ", "run engine in dedicated mode")
|
||||
@@ -1158,7 +1159,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
Host_RunTests( 1 );
|
||||
#endif
|
||||
|
||||
FS_LoadGameInfo( NULL );
|
||||
FS_LoadGameInfo();
|
||||
Cvar_PostFSInit();
|
||||
|
||||
Image_CheckPaletteQ1 ();
|
||||
@@ -1322,7 +1323,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_RemoveCommand( "setgl" );
|
||||
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
FS_CheckConfig();
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
|
||||
Cbuf_AddTextf( "timedemo %s\n", demoname );
|
||||
|
||||
@@ -1368,6 +1368,21 @@ void FS_Rescan( uint32_t flags, const char *language )
|
||||
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH | flags );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
FS_Gamedir
|
||||
|
||||
Allows engine to know game directory before gameinfo is initialized
|
||||
===============
|
||||
*/
|
||||
static const char *FS_Gamedir( void )
|
||||
{
|
||||
if( GI )
|
||||
return GI->gamefolder;
|
||||
|
||||
return fs_gamedir;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_LoadGameInfo
|
||||
@@ -1375,17 +1390,14 @@ FS_LoadGameInfo
|
||||
can be passed null arg
|
||||
================
|
||||
*/
|
||||
void FS_LoadGameInfo( const char *rootfolder )
|
||||
static void FS_LoadGameInfo( uint32_t flags, const char *language )
|
||||
{
|
||||
int i;
|
||||
|
||||
// lock uplevel of gamedir for read\write
|
||||
FS_AllowDirectPaths( false );
|
||||
|
||||
if( rootfolder )
|
||||
Q_strncpy( fs_gamedir, rootfolder, sizeof( fs_gamedir ));
|
||||
|
||||
Con_Reportf( "%s( %s )\n", __func__, fs_gamedir );
|
||||
Con_Reportf( "%s( %s, 0x%x, %s )\n", __func__, fs_gamedir, flags, language );
|
||||
|
||||
// clear any old paths
|
||||
FS_ClearSearchPath();
|
||||
@@ -1410,7 +1422,7 @@ void FS_LoadGameInfo( const char *rootfolder )
|
||||
FS_CreatePath( buf );
|
||||
}
|
||||
|
||||
FS_Rescan( 0, NULL ); // create new filesystem
|
||||
FS_Rescan( flags, language ); // create new filesystem
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3461,6 +3473,7 @@ const fs_api_t g_api =
|
||||
FS_Path_f,
|
||||
|
||||
// gameinfo utils
|
||||
FS_Gamedir,
|
||||
FS_LoadGameInfo,
|
||||
|
||||
// file ops
|
||||
|
||||
@@ -32,8 +32,8 @@ extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define FS_API_VERSION 3 // not stable yet!
|
||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
||||
#define FS_API_VERSION 4 // not stable yet!
|
||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem004" // follow FS_API_VERSION!!!
|
||||
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
||||
|
||||
// search path flags
|
||||
@@ -167,7 +167,8 @@ typedef struct fs_api_t
|
||||
void (*Path_f)( void );
|
||||
|
||||
// gameinfo utils
|
||||
void (*LoadGameInfo)( const char *rootfolder );
|
||||
const char *(*Gamedir)( void );
|
||||
void (*LoadGameInfo)( uint32_t flags, const char *language );
|
||||
|
||||
// file ops
|
||||
file_t *(*Open)( const char *filepath, const char *mode, qboolean gamedironly );
|
||||
|
||||
@@ -166,9 +166,6 @@ int FS_SetCurrentDirectory( const char *path );
|
||||
qboolean FS_GetRootDirectory( char *path, size_t size );
|
||||
void FS_Path_f( void );
|
||||
|
||||
// gameinfo utils
|
||||
void FS_LoadGameInfo( const char *rootfolder );
|
||||
|
||||
// file ops
|
||||
int FS_Close( file_t *file );
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
|
||||
@@ -42,9 +42,6 @@ extern fs_globals_t *FI;
|
||||
#define FS_SetCurrentDirectory (*g_fsapi.SetCurrentDirectory)
|
||||
#define FS_Path_f (*g_fsapi.Path_f)
|
||||
|
||||
// gameinfo utils
|
||||
#define FS_LoadGameInfo (*g_fsapi.LoadGameInfo)
|
||||
|
||||
// file ops
|
||||
#ifndef FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#define FS_Open (*g_fsapi.Open)
|
||||
|
||||
Reference in New Issue
Block a user