diff options
Diffstat (limited to 'src/qcommon')
| -rw-r--r-- | src/qcommon/cvar.c | 9 | ||||
| -rw-r--r-- | src/qcommon/files.c | 133 | ||||
| -rw-r--r-- | src/qcommon/q_shared.h | 1 | ||||
| -rw-r--r-- | src/qcommon/qcommon.h | 11 | 
4 files changed, 139 insertions, 15 deletions
diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c index d22679e8..cabaf98f 100644 --- a/src/qcommon/cvar.c +++ b/src/qcommon/cvar.c @@ -403,6 +403,9 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {  		// ZOID--needs to be set so that cvars the game sets as   		// SERVERINFO get sent to clients  		cvar_modifiedFlags |= flags; +		if ( flags & CVAR_ALTERNATE_SYSTEMINFO ) { +			cvar_modifiedFlags |= CVAR_SYSTEMINFO; +		}  		return var;  	} @@ -452,6 +455,9 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {  	var->flags = flags;  	// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)  	cvar_modifiedFlags |= var->flags; +	if ( var->flags & CVAR_ALTERNATE_SYSTEMINFO ) { +		cvar_modifiedFlags |= CVAR_SYSTEMINFO; +	}  	hash = generateHashValue(var_name);  	var->hashIndex = hash; @@ -555,6 +561,9 @@ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {  	// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)  	cvar_modifiedFlags |= var->flags; +	if ( var->flags & CVAR_ALTERNATE_SYSTEMINFO ) { +		cvar_modifiedFlags |= CVAR_SYSTEMINFO; +	}  	if (!force)  	{ diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 27902711..e172f528 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -192,7 +192,7 @@ typedef struct fileInPack_s {  	struct	fileInPack_s*	next;		// next file in the hash  } fileInPack_t; -typedef struct { +typedef struct pack_s {  	char			pakPathname[MAX_OSPATH];	// /tremulous/baseq3  	char			pakFilename[MAX_OSPATH];	// /tremulous/base/pak0.pk3  	char			pakBasename[MAX_OSPATH];	// pak0 @@ -205,6 +205,9 @@ typedef struct {  	int				hashSize;					// hash table size (power of 2)  	fileInPack_t*	*hashTable;					// hash table  	fileInPack_t*	buildBuffer;				// buffer with the filenames etc. +	qboolean		onlyPrimary; +	qboolean		onlyAlternate; +	struct pack_s	*primaryVersion;  } pack_t;  typedef struct { @@ -1716,7 +1719,11 @@ CONVENIENCE FUNCTIONS FOR ENTIRE FILES  ======================================================================================  */ -int	FS_FileIsInPAK(const char *filename, int *pChecksum ) { +int	FS_FileIsInPAK( const char *filename, int *pChecksum ) { +	return FS_FileIsInPAK_A( qfalse, filename, pChecksum ); +} + +int	FS_FileIsInPAK_A( qboolean alternate, const char *filename, int *pChecksum ) {  	searchpath_t	*search;  	pack_t			*pak;  	fileInPack_t	*pakFile; @@ -1757,6 +1764,9 @@ int	FS_FileIsInPAK(const char *filename, int *pChecksum ) {  			if ( !FS_PakIsPure(search->pack) ) {  				continue;  			} +			if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +				continue; +			}  			// look through all the pak file elements  			pak = search->pack; @@ -2732,7 +2742,10 @@ void FS_Path_f( void ) {  	Com_Printf ("We are looking in the current search path:\n");  	for (s = fs_searchpaths; s; s = s->next) {  		if (s->pack) { -			Com_Printf ("%s (%i files)\n", s->pack->pakFilename, s->pack->numfiles); +			Com_Printf ("%s (%i files%s)\n", s->pack->pakFilename, s->pack->numfiles, +				s->pack->onlyPrimary ? ", not for 1.1" : s->pack->onlyAlternate ? ", only for 1.1" : ""); +			if (s->pack->primaryVersion) +				Com_Printf ("        (the 1.1 version of %s)\n", s->pack->primaryVersion->pakFilename);  			if ( fs_numServerPaks ) {  				if ( !FS_PakIsPure(s->pack) ) {  					Com_Printf( "    not on the pure list\n" ); @@ -2869,6 +2882,14 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {  	int				pakwhich;  	int				len; +	char			prefixBuf[MAX_STRING_CHARS]; +	char			*p; +	const char		*prefixes[10][2]; +	int				lengths[10][2]; +	int				numPairs, i; +	searchpath_t	*otherSearchpaths; +	searchpath_t	*srch; +  	// Unique  	for ( sp = fs_searchpaths ; sp ; sp = sp->next ) {  		if ( sp->dir && !Q_stricmp(sp->dir->path, path) && !Q_stricmp(sp->dir->gamedir, dir)) { @@ -2897,6 +2918,42 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {  		qsort( pakdirs, numdirs, sizeof(char *), paksort );  	} +	Q_strncpyz( prefixBuf, Cvar_VariableString( "fs_pk3PrefixPairs" ), sizeof( prefixBuf ) ); +	numPairs = 0; +	p = prefixBuf; +	if ( !p[0] ) +		p = NULL; +	while ( p ) { +		prefixes[numPairs][0] = p; +		p = strchr( p, '&' ); +		if ( !p ) { +			Com_Printf( S_COLOR_YELLOW "WARNING: fs_pk3PrefixPairs ends with an incomplete pair\n" ); +			break; +		} +		lengths[numPairs][0] = (int)( p - prefixes[numPairs][0] ); +		*p++ = '\0'; +		prefixes[numPairs][1] = p; +		p = strchr( p, '|' ); +		if ( p ) { +			lengths[numPairs][1] = (int)( p - prefixes[numPairs][1] ); +			*p++ = '\0'; +		} else { +			lengths[numPairs][1] = (int)strlen( prefixes[numPairs][1] ); +		} +		if ( lengths[numPairs][0] == 0 && lengths[numPairs][1] == 0 ) { +			Com_Printf( S_COLOR_YELLOW "WARNING: fs_pk3PrefixPairs contains a null-null pair, skipping this pair\n" ); +			continue; +		} +		if ( lengths[numPairs][0] != 0 && lengths[numPairs][1] != 0 && +			!Q_stricmpn( prefixes[numPairs][0], prefixes[numPairs][1], MIN( lengths[numPairs][0], lengths[numPairs][1] ) ) ) { +			Com_Printf( S_COLOR_YELLOW "WARNING: in fs_pk3PrefixPairs, one of '%s' and '%s' is a real prefix of the other, skipping this pair\n", +				prefixes[numPairs][0], prefixes[numPairs][1] ); +			continue; +		} +		++numPairs; +	} +	otherSearchpaths = fs_searchpaths; +  	pakfilesi = 0;  	pakdirsi = 0; @@ -2939,6 +2996,20 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {  			search->next = fs_searchpaths;  			fs_searchpaths = search; +			pak->onlyPrimary = qfalse; +			pak->onlyAlternate = qfalse; +			for ( i = 0 ; i < numPairs ; ++i ) { +				if ( lengths[i][0] != 0 && !Q_stricmpn( pak->pakBasename, prefixes[i][0], lengths[i][0] ) ) { +					pak->onlyPrimary = qtrue; +					break; +				} +				else if ( lengths[i][1] != 0 && !Q_stricmpn( pak->pakBasename, prefixes[i][1], lengths[i][1] ) ) { +					pak->onlyAlternate = qtrue; +					break; +				} +			} +			pak->primaryVersion = NULL; +  			pakfilesi++;  		}  		else { @@ -2972,6 +3043,29 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {  	Sys_FreeFileList( pakfiles );  	Sys_FreeFileList( pakdirs ); +	if ( numPairs > 0 ) { +		int bnlengths[2]; +		for ( search = fs_searchpaths ; search != otherSearchpaths ; search = search->next ) { +			if ( !( search->pack && search->pack->onlyPrimary ) ) { +				continue; +			} +			bnlengths[0] = (int)strlen( search->pack->pakBasename ); +			for ( srch = fs_searchpaths ; srch != otherSearchpaths ; srch = srch->next ) { +				if ( !( srch->pack && srch->pack->onlyAlternate ) ) { +					continue; +				} +				bnlengths[1] = (int)strlen( srch->pack->pakBasename ); +				for ( i = 0 ; i < numPairs ; ++i ) { +					if ( lengths[i][0] != 0 && lengths[i][1] != 0 && bnlengths[0] >= lengths[i][0] && bnlengths[1] >= lengths[i][1] && +						!Q_stricmp( search->pack->pakBasename + lengths[i][0], srch->pack->pakBasename + lengths[i][1] ) ) { +						srch->pack->primaryVersion = search->pack; +						break; +					} +				} +			} +		} +	} +  	//  	// add the directory to the search path  	// @@ -3230,6 +3324,7 @@ static void FS_Startup( const char *gameName )  	}  	fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT|CVAR_PROTECTED );  	fs_gamedirvar = Cvar_Get ("fs_game", "gpp", CVAR_INIT|CVAR_SYSTEMINFO ); +	Cvar_Get( "fs_pk3PrefixPairs", "", CVAR_ARCHIVE|CVAR_LATCH );  	// add search path elements in reverse priority order  	if (fs_basepath->string[0]) { @@ -3304,7 +3399,7 @@ Returns a space separated string containing the checksums of all loaded pk3 file  Servers with sv_pure set will get this string and pass it to clients.  =====================  */ -const char *FS_LoadedPakChecksums( void ) { +const char *FS_LoadedPakChecksums( qboolean alternate ) {  	static char	info[BIG_INFO_STRING];  	searchpath_t	*search; @@ -3315,6 +3410,9 @@ const char *FS_LoadedPakChecksums( void ) {  		if ( !search->pack ) {  			continue;  		} +		if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +			continue; +		}  		Q_strcat( info, sizeof( info ), va("%i ", search->pack->checksum ) );  	} @@ -3330,7 +3428,7 @@ Returns a space separated string containing the names of all loaded pk3 files.  Servers with sv_pure set will get this string and pass it to clients.  =====================  */ -const char *FS_LoadedPakNames( void ) { +const char *FS_LoadedPakNames( qboolean alternate ) {  	static char	info[BIG_INFO_STRING];  	searchpath_t	*search; @@ -3341,6 +3439,9 @@ const char *FS_LoadedPakNames( void ) {  		if ( !search->pack ) {  			continue;  		} +		if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +			continue; +		}  		if (*info) {  			Q_strcat(info, sizeof( info ), " " ); @@ -3360,7 +3461,7 @@ Servers with sv_pure use these checksums to compare with the checksums the clien  back to the server.  =====================  */ -const char *FS_LoadedPakPureChecksums( void ) { +const char *FS_LoadedPakPureChecksums( qboolean alternate ) {  	static char	info[BIG_INFO_STRING];  	searchpath_t	*search; @@ -3371,6 +3472,9 @@ const char *FS_LoadedPakPureChecksums( void ) {  		if ( !search->pack ) {  			continue;  		} +		if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +			continue; +		}  		Q_strcat( info, sizeof( info ), va("%i ", search->pack->pure_checksum ) );  	} @@ -3386,7 +3490,7 @@ Returns a space separated string containing the checksums of all referenced pk3  The server will send this to the clients so they can check which files should be auto-downloaded.   =====================  */ -const char *FS_ReferencedPakChecksums( void ) { +const char *FS_ReferencedPakChecksums( qboolean alternate ) {  	static char	info[BIG_INFO_STRING];  	searchpath_t *search; @@ -3396,7 +3500,11 @@ const char *FS_ReferencedPakChecksums( void ) {  	for ( search = fs_searchpaths ; search ; search = search->next ) {  		// is the element a pak file?  		if ( search->pack ) { -			if (search->pack->referenced || Q_stricmpn(search->pack->pakGamename, BASEGAME, strlen(BASEGAME))) { +			if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +				continue; +			} +			if (search->pack->referenced || (search->pack->primaryVersion && search->pack->primaryVersion->referenced) || +				(fs_gamedirvar->string[0] && Q_stricmp(fs_gamedirvar->string, BASEGAME) && !Q_stricmp(search->pack->pakGamename, fs_gamedirvar->string))) {  				Q_strcat( info, sizeof( info ), va("%i ", search->pack->checksum ) );  			}  		} @@ -3460,7 +3568,7 @@ Returns a space separated string containing the names of all referenced pk3 file  The server will send this to the clients so they can check which files should be auto-downloaded.   =====================  */ -const char *FS_ReferencedPakNames( void ) { +const char *FS_ReferencedPakNames( qboolean alternate ) {  	static char	info[BIG_INFO_STRING];  	searchpath_t	*search; @@ -3471,7 +3579,11 @@ const char *FS_ReferencedPakNames( void ) {  	for ( search = fs_searchpaths ; search ; search = search->next ) {  		// is the element a pak file?  		if ( search->pack ) { -			if (search->pack->referenced || Q_stricmpn(search->pack->pakGamename, BASEGAME, strlen(BASEGAME))) { +			if ( ( alternate && search->pack->onlyPrimary ) || ( !alternate && search->pack->onlyAlternate ) ) { +				continue; +			} +			if (search->pack->referenced || (search->pack->primaryVersion && search->pack->primaryVersion->referenced) || +				(fs_gamedirvar->string[0] && Q_stricmp(fs_gamedirvar->string, BASEGAME) && !Q_stricmp(search->pack->pakGamename, fs_gamedirvar->string))) {  				if (*info) {  					Q_strcat(info, sizeof( info ), " " );  				} @@ -3634,6 +3746,7 @@ void FS_InitFilesystem( void ) {  	Com_StartupVariable("fs_basepath");  	Com_StartupVariable("fs_homepath");  	Com_StartupVariable("fs_game"); +	Com_StartupVariable("fs_pk3PrefixPairs");  	if(!FS_FilenameCompare(Cvar_VariableString("fs_game"), BASEGAME))  		Cvar_Set("fs_game", ""); diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 6d6aa461..1ec69f44 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -959,6 +959,7 @@ default values.  #define CVAR_SERVER_CREATED	0x0800	// cvar was created by a server the client connected to.  #define CVAR_VM_CREATED		0x1000	// cvar was created exclusively in one of the VMs.  #define CVAR_PROTECTED		0x2000	// prevent modifying this var from VMs or the server +#define CVAR_ALTERNATE_SYSTEMINFO	0x1000000  // These flags are only returned by the Cvar_Flags() function  #define CVAR_MODIFIED		0x40000000	// Cvar was modified  #define CVAR_NONEXISTENT	0x80000000	// Cvar doesn't exist. diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index 895c01d4..5dc5ab0c 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -647,6 +647,7 @@ long		FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFI  // file IO goes through FS_ReadFile, which Does The Right Thing already.  int		FS_FileIsInPAK(const char *filename, int *pChecksum ); +int		FS_FileIsInPAK_A(qboolean alternate, const char *filename, int *pChecksum );  // returns 1 if a file is in the PAK file, otherwise -1  int		FS_Write( const void *buffer, int len, fileHandle_t f ); @@ -695,14 +696,14 @@ int		FS_Seek( fileHandle_t f, long offset, int origin );  qboolean FS_FilenameCompare( const char *s1, const char *s2 ); -const char *FS_LoadedPakNames( void ); -const char *FS_LoadedPakChecksums( void ); -const char *FS_LoadedPakPureChecksums( void ); +const char *FS_LoadedPakNames( qboolean alternate ); +const char *FS_LoadedPakChecksums( qboolean alternate ); +const char *FS_LoadedPakPureChecksums( qboolean alternate );  // Returns a space separated string containing the checksums of all loaded pk3 files.  // Servers with sv_pure set will get this string and pass it to clients. -const char *FS_ReferencedPakNames( void ); -const char *FS_ReferencedPakChecksums( void ); +const char *FS_ReferencedPakNames( qboolean alternate ); +const char *FS_ReferencedPakChecksums( qboolean alternate );  const char *FS_ReferencedPakPureChecksums( void );  // Returns a space separated string containing the checksums of all loaded   // AND referenced pk3 files. Servers with sv_pure set will get this string   | 
