Exemple #1
0
/*
=================
Host_RegisterDecal
=================
*/
qboolean Host_RegisterDecal( const char *name )
{
	char	shortname[CS_SIZE];
	int	i;

	if( !name || !name[0] )
		return 0;

	FS_FileBase( name, shortname );

	for( i = 1; i < MAX_DECALS && host.draw_decals[i][0]; i++ )
	{
		if( !Q_stricmp( (char *)host.draw_decals[i], shortname ))
			return true;
	}

	if( i == MAX_DECALS )
	{
		MsgDev( D_ERROR, "Host_RegisterDecal: MAX_DECALS limit exceeded\n" );
		return false;
	}

	// register new decal
	Q_strncpy( (char *)host.draw_decals[i], shortname, sizeof( host.draw_decals[i] ));
	num_decals++;

	return true;
}
Exemple #2
0
/*
====================
CL_UpdateTexture

Update texture top and bottom colors
====================
*/
void CL_UpdateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
{
	gltexture_t	*glt;
	rgbdata_t		*pic;
	texture_t		*tx = NULL;
	char		texname[128], name[128], mdlname[128];
	int		i, index;
	size_t size;
	byte		paletteBackup[768];
	byte		*raw, *pal;

	// save of the real texture index
	glt = R_GetTexture( ptexture->index );

	// build name of original texture
	Q_strncpy( mdlname, RI.currentmodel->name, sizeof( mdlname ));
	FS_FileBase( ptexture->name, name );
	FS_StripExtension( mdlname );

	Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
	index = GL_FindTexture( texname );
	if( !index ) return; // couldn't find texture

	// search for pixels
	for( i = 0; i < RI.currentmodel->numtextures; i++ )
	{
		tx = RI.currentmodel->textures[i];
		if( tx->gl_texturenum == index )
			break; // found
	}

	ASSERT( tx != NULL );

	// backup original palette
	pal = (byte *)(tx + 1) + (tx->width * tx->height);
	Q_memcpy( paletteBackup, pal, 768 );

	raw = CL_CreateRawTextureFromPixels( tx, &size, topcolor, bottomcolor );
	pic = FS_LoadImage( glt->name, raw, size );
	if( !pic )
	{
		MsgDev( D_ERROR, "Couldn't update texture %s\n", glt->name );
		return;
	}

	index = GL_LoadTextureInternal( glt->name, pic, 0, true );
	FS_FreeImage( pic );

	// restore original palette
	Q_memcpy( pal, paletteBackup, 768 );

	ASSERT( index == ptexture->index );
}
Exemple #3
0
/*
=====================================
Cmd_GetMusicList

Prints or complete background track filename
=====================================
*/
qboolean Cmd_GetMusicList( const char *s, char *completedname, int length )
{
	search_t		*t;
	string		matchbuf;
	int		i, numtracks;

	t = FS_Search( va( "media/%s*.*", s ), true, false );
	if( !t ) return false;

	FS_FileBase( t->filenames[0], matchbuf ); 
	if( completedname && length ) Q_strncpy( completedname, matchbuf, length );
	if( t->numfilenames == 1 ) return true;

	for(i = 0, numtracks = 0; i < t->numfilenames; i++)
	{
		const char *ext = FS_FileExtension( t->filenames[i] ); 

		if( !Q_stricmp( ext, "wav" ) || !Q_stricmp( ext, "mp3" ));
		else continue;

		FS_FileBase( t->filenames[i], matchbuf );
		Msg( "%16s\n", matchbuf );
		numtracks++;
	}

	Msg( "\n^3 %i soundtracks found.\n", numtracks );
	Mem_Free(t);

	// cut shortestMatch to the amount common with s
	if( completedname && length )
	{
		for( i = 0; matchbuf[i]; i++ )
		{
			if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
				completedname[i] = 0;
		}
	}
	return true;
}
Exemple #4
0
/*
=====================================
Cmd_GetItemsList

Prints or complete item classname (weapons only)
=====================================
*/
qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
{
	search_t		*t;
	string		matchbuf;
	int		i, numitems;

	if( !clgame.itemspath[0] ) return false; // not in game yet
	t = FS_Search( va( "%s/%s*.txt", clgame.itemspath, s ), true, false );
	if( !t ) return false;

	FS_FileBase( t->filenames[0], matchbuf ); 
	if( completedname && length ) Q_strncpy( completedname, matchbuf, length );
	if( t->numfilenames == 1 ) return true;

	for(i = 0, numitems = 0; i < t->numfilenames; i++)
	{
		const char *ext = FS_FileExtension( t->filenames[i] ); 

		if( Q_stricmp( ext, "txt" )) continue;
		FS_FileBase( t->filenames[i], matchbuf );
		Msg( "%16s\n", matchbuf );
		numitems++;
	}

	Msg( "\n^3 %i items found.\n", numitems );
	Mem_Free( t );

	// cut shortestMatch to the amount common with s
	if( completedname && length )
	{
		for( i = 0; matchbuf[i]; i++ )
		{
			if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
				completedname[i] = 0;
		}
	}
	return true;
}
Exemple #5
0
/*
=====================================
Cmd_GetSavesList

Prints or complete savegame filename
=====================================
*/
qboolean Cmd_GetSavesList( const char *s, char *completedname, int length )
{
	search_t		*t;
	string		matchbuf;
	int		i, numsaves;

	t = FS_Search( va( "save/%s*.sav", s ), true, true );	// lookup only in gamedir
	if( !t ) return false;

	FS_FileBase( t->filenames[0], matchbuf ); 
	if( completedname && length ) Q_strncpy( completedname, matchbuf, length );
	if( t->numfilenames == 1 ) return true;

	for( i = 0, numsaves = 0; i < t->numfilenames; i++ )
	{
		const char *ext = FS_FileExtension( t->filenames[i] ); 

		if( Q_stricmp( ext, "sav" )) continue;
		FS_FileBase( t->filenames[i], matchbuf );
		Msg( "%16s\n", matchbuf );
		numsaves++;
	}

	Msg( "\n^3 %i saves found.\n", numsaves );
	Mem_Free( t );

	// cut shortestMatch to the amount common with s
	if( completedname && length )
	{
		for( i = 0; matchbuf[i]; i++ )
		{
			if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
				completedname[i] = 0;
		}
	}

	return true;
}
Exemple #6
0
//-----------------------------------------------------------------------------
// Purpose: Called by CSaveRestore::SaveClientState
// Input  : *pList - 
// Output : int
//-----------------------------------------------------------------------------
int R_CreateDecalList( decallist_t *pList, qboolean changelevel )
{
	int	total = 0;
	int	i, depth;

	if( cl.worldmodel )
	{
		for( i = 0; i < MAX_RENDER_DECALS; i++ )
		{
			decal_t	*decal = &gDecalPool[i];
			decal_t	*pdecals;
			
			// decal is in use and is not a custom decal
			if( decal->psurface == NULL || ( decal->flags & FDECAL_DONTSAVE ))	
				 continue;

			// compute depth
			depth = 0;
			pdecals = decal->psurface->pdecals;

			while( pdecals && pdecals != decal )
			{
				depth++;
				pdecals = pdecals->pnext;
			}

			pList[total].depth = depth;
			pList[total].flags = decal->flags;
			pList[total].scale = decal->scale;
			
			R_DecalUnProject( decal, &pList[total] );
			FS_FileBase( R_GetTexture( decal->texture )->name, pList[total].name );

			// check to see if the decal should be added
			total = DecalListAdd( pList, total );
		}

		if( clgame.drawFuncs.R_CreateStudioDecalList )
		{
			total += clgame.drawFuncs.R_CreateStudioDecalList( pList, total, changelevel );
		}
	}

	// sort the decals lowest depth first, so they can be re-applied in order
	qsort( pList, total, sizeof( decallist_t ), DecalDepthCompare );

	return total;
}
Exemple #7
0
void SV_Reload_f( void )
{
	const char	*save;
	string		loadname;

	if( sv.state != ss_active || sv.background )
		return;

	save = SV_GetLatestSave();
	if( save )
	{
		FS_FileBase( save, loadname );
		Cbuf_AddText( va( "load %s\n", loadname ));
	}
	else Cbuf_AddText( "newgame\n" ); // begin new game
}
Exemple #8
0
/*
====================
StudioGetAnim

====================
*/
static mstudioanim_t *Mod_StudioGetAnim( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc )
{
	mstudioseqgroup_t	*pseqgroup;
	fs_offset_t		filesize;
	byte		*buf;
	cache_user_t *paSequences;

	pseqgroup = (mstudioseqgroup_t *)((byte *)mod_studiohdr + mod_studiohdr->seqgroupindex) + pseqdesc->seqgroup;
	if( pseqdesc->seqgroup == 0 )
		return (mstudioanim_t *)((byte *)mod_studiohdr + pseqdesc->animindex);

	paSequences = (cache_user_t *)m_pSubModel->submodels;

	if( paSequences == NULL )
	{
		paSequences = (cache_user_t *)Mem_Alloc( com_studiocache, MAXSTUDIOGROUPS * sizeof( cache_user_t ));
		m_pSubModel->submodels = (void *)paSequences;
	}

	// check for already loaded
	if( !paSequences[pseqdesc->seqgroup].data )
	{
		string	filepath, modelname, modelpath;

		FS_FileBase( m_pSubModel->name, modelname );
		FS_ExtractFilePath( m_pSubModel->name, modelpath );
		Q_snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 );

		buf = FS_LoadFile( filepath, &filesize, false );
		if( !buf || !filesize )
			Host_Error( "StudioGetAnim: can't load %s\n", filepath );
		else if( IDSEQGRPHEADER != *(uint *)buf )
			Host_Error( "StudioGetAnim: %s is corrupted\n", filepath );

		MsgDev( D_INFO, "loading: %s\n", filepath );

		paSequences[pseqdesc->seqgroup].data = Mem_Alloc( com_studiocache, filesize );
		Q_memcpy( paSequences[pseqdesc->seqgroup].data, buf, (size_t)filesize );
		Mem_Free( buf );
	}
	return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex);
}
Exemple #9
0
/*
===============
R_ShowTextures

Draw all the images to the screen, on top of whatever
was there.  This is used to test for texture thrashing.
===============
*/
void R_ShowTextures( void )
{
	gltexture_t	*image;
	float		x, y, w, h;
	int		i, j, k, base_w, base_h;
	int		total, start, end;
	rgba_t		color = { 192, 192, 192, 255 };
	int		charHeight, numTries = 0;
	static qboolean	showHelp = true;
	string		shortname;

	if( !gl_showtextures->integer )
		return;

	if( showHelp )
	{
		CL_CenterPrint( "use '<-' and '->' keys to view all the textures", 0.25f );
		showHelp = false;
	}

	pglClear( GL_COLOR_BUFFER_BIT );
	pglFinish();

	base_w = 8;
	base_h = 6;

rebuild_page:
	total = base_w * base_h;
	start = total * (gl_showtextures->integer - 1);
	end = total * gl_showtextures->integer;
	if( end > MAX_TEXTURES ) end = MAX_TEXTURES;

	w = glState.width / (float)base_w;
	h = glState.height / (float)base_h;

	Con_DrawStringLen( NULL, NULL, &charHeight );

	for( i = j = 0; i < MAX_TEXTURES; i++ )
	{
		image = R_GetTexture( i );
		if( j == start ) break; // found start
		if( pglIsTexture( image->texnum )) j++;
	}

	if( i == MAX_TEXTURES && gl_showtextures->integer != 1 )
	{
		// bad case, rewind to one and try again
		Cvar_SetFloat( "r_showtextures", max( 1, gl_showtextures->integer - 1 ));
		if( ++numTries < 2 ) goto rebuild_page;	// to prevent infinite loop
	}

	for( k = 0; i < MAX_TEXTURES; i++ )
	{
		if( j == end ) break; // page is full

		image = R_GetTexture( i );
		if( !pglIsTexture( image->texnum ))
			continue;

		x = k % base_w * w;
		y = k / base_w * h;

		pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
		GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes

		if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE ))
			pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );

		pglBegin( GL_QUADS );
		pglTexCoord2f( 0, 0 );
		pglVertex2f( x, y );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( image->width, 0 );
		else pglTexCoord2f( 1, 0 );
		pglVertex2f( x + w, y );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( image->width, image->height );
		else pglTexCoord2f( 1, 1 );
		pglVertex2f( x + w, y + h );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( 0, image->height );
		else pglTexCoord2f( 0, 1 );
		pglVertex2f( x, y + h );
		pglEnd();

		if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE ))
			pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );

		FS_FileBase( image->name, shortname );
		if( Q_strlen( shortname ) > 18 )
		{
			// cutoff too long names, it looks ugly
			shortname[16] = '.';
			shortname[17] = '.';
			shortname[18] = '\0';
		}
		Con_DrawString( x + 1, y + h - charHeight, shortname, color );
		j++, k++;
	}

	CL_DrawCenterPrint ();
	pglFinish();
}
Exemple #10
0
qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
{
	byte	buf[MAX_SYSPATH];
	char	*buffer;
	string	result;
	int	i, size;
	search_t	*t;
	file_t	*f;

	if( FS_FileSize( "maps.lst", onlyingamedir ) > 0 && !fRefresh )
	{
		MsgDev( D_NOTE, "maps.lst is exist: %s\n", onlyingamedir ? "basedir" : "gamedir" );
		return true; // exist 
	}

	t = FS_Search( "maps/*.bsp", false, onlyingamedir );

	if( !t )
	{
		if( onlyingamedir )
		{
			// mod doesn't contain any maps (probably this is a bot)
			return Cmd_CheckMapsList_R( fRefresh, false );
		}

		return false;
	}

	buffer = Mem_Alloc( host.mempool, t->numfilenames * 2 * sizeof( result ));

	for( i = 0; i < t->numfilenames; i++ )
	{
		char		*ents = NULL, *pfile;
		int		ver = -1, lumpofs = 0, lumplen = 0;
		string		mapname, message, entfilename;
		const char	*ext = FS_FileExtension( t->filenames[i] ); 

		if( Q_stricmp( ext, "bsp" )) continue;
		f = FS_Open( t->filenames[i], "rb", onlyingamedir );
		FS_FileBase( t->filenames[i], mapname );

		if( f )
		{
			int	num_spawnpoints = 0;
			dheader_t	*header;

			Q_memset( buf, 0, MAX_SYSPATH );
			FS_Read( f, buf, MAX_SYSPATH );
			ver = *(uint *)buf;
                              
			switch( ver )
			{
			case Q1BSP_VERSION:
			case HLBSP_VERSION:
			case XTBSP_VERSION:
				header = (dheader_t *)buf;
				if( header->lumps[LUMP_ENTITIES].fileofs <= 1024 )
				{
					lumpofs = header->lumps[LUMP_PLANES].fileofs;
					lumplen = header->lumps[LUMP_PLANES].filelen;
				}
				else
				{
					lumpofs = header->lumps[LUMP_ENTITIES].fileofs;
					lumplen = header->lumps[LUMP_ENTITIES].filelen;
				}
				break;
			}

			Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename ));
			FS_StripExtension( entfilename );
			FS_DefaultExtension( entfilename, ".ent" );
			ents = FS_LoadFile( entfilename, NULL, true );

			if( !ents && lumplen >= 10 )
			{
				FS_Seek( f, lumpofs, SEEK_SET );
				ents = (char *)Mem_Alloc( host.mempool, lumplen + 1 );
				FS_Read( f, ents, lumplen );
			}

			if( ents )
			{
				// if there are entities to parse, a missing message key just
				// means there is no title, so clear the message string now
				char	token[2048];
				qboolean	worldspawn = true;

				Q_strncpy( message, "No Title", MAX_STRING );
				pfile = ents;

				while(( pfile = COM_ParseFile( pfile, token )) != NULL )
				{
					if( token[0] == '}' && worldspawn )
						worldspawn = false;
					else if( !Q_strcmp( token, "message" ) && worldspawn )
					{
						// get the message contents
						pfile = COM_ParseFile( pfile, message );
					}
					else if( !Q_strcmp( token, "classname" ))
					{
						pfile = COM_ParseFile( pfile, token );
						if( !Q_strcmp( token, GI->mp_entity ))
							num_spawnpoints++;
					}
					if( num_spawnpoints ) break; // valid map
				}
				Mem_Free( ents );
			}

			if( f ) FS_Close( f );

			if( num_spawnpoints )
			{
				// format: mapname "maptitle"\n
				Q_sprintf( result, "%s \"%s\"\n", mapname, message );
				Q_strcat( buffer, result ); // add new string
			}
		}
	}

	if( t ) Mem_Free( t ); // free search result
	size = Q_strlen( buffer );

	if( !size )
	{
          	if( buffer ) Mem_Free( buffer );

		if( onlyingamedir )
			return Cmd_CheckMapsList_R( fRefresh, false );
		return false;
	}

	// write generated maps.lst
	if( FS_WriteFile( "maps.lst", buffer, Q_strlen( buffer )))
	{
          	if( buffer ) Mem_Free( buffer );
		return true;
	}
	return false;
}
Exemple #11
0
/*
=====================================
Cmd_GetMapList

Prints or complete map filename
=====================================
*/
qboolean Cmd_GetMapList( const char *s, char *completedname, int length )
{
	search_t		*t;
	file_t		*f;
	string		message;
	string		matchbuf;
	byte		buf[MAX_SYSPATH]; // 1 kb
	int		i, nummaps;

	t = FS_Search( va( "maps/%s*.bsp", s ), true, con_gamemaps->integer );
	if( !t ) return false;

	FS_FileBase( t->filenames[0], matchbuf ); 
	Q_strncpy( completedname, matchbuf, length );
	if( t->numfilenames == 1 ) return true;

	for( i = 0, nummaps = 0; i < t->numfilenames; i++ )
	{
		char		entfilename[CS_SIZE];
		int		ver = -1, mapver = -1, lumpofs = 0, lumplen = 0;
		const char	*ext = FS_FileExtension( t->filenames[i] ); 
		char		*ents = NULL, *pfile;
		qboolean		paranoia = false;
		qboolean		gearbox = false;
			
		if( Q_stricmp( ext, "bsp" )) continue;
		Q_strncpy( message, "^1error^7", sizeof( message ));
		f = FS_Open( t->filenames[i], "rb", con_gamemaps->integer );
	
		if( f )
		{
			dheader_t	*header;
			dextrahdr_t	*hdrext;

			Q_memset( buf, 0, sizeof( buf ));
			FS_Read( f, buf, sizeof( buf ));
			header = (dheader_t *)buf;
			ver = header->version;
                              
			switch( ver )
			{
			case Q1BSP_VERSION:
			case HLBSP_VERSION:
			case XTBSP_VERSION:
				if( header->lumps[LUMP_ENTITIES].fileofs <= 1024 && !(header->lumps[LUMP_ENTITIES].filelen % sizeof(dplane_t)))
				{
					lumpofs = header->lumps[LUMP_PLANES].fileofs;
					lumplen = header->lumps[LUMP_PLANES].filelen;
					gearbox = true;
				}
				else
				{
					lumpofs = header->lumps[LUMP_ENTITIES].fileofs;
					lumplen = header->lumps[LUMP_ENTITIES].filelen;
					gearbox = false;
				}
				break;
			}

			if( ver == XTBSP_VERSION )
				hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader31_t ));
			else hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader_t ));

			if( hdrext->id == IDEXTRAHEADER && hdrext->version == EXTRA_VERSION )
				paranoia = true;

			Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename ));
			FS_StripExtension( entfilename );
			FS_DefaultExtension( entfilename, ".ent" );
			ents = FS_LoadFile( entfilename, NULL, true );

			if( !ents && lumplen >= 10 )
			{
				FS_Seek( f, lumpofs, SEEK_SET );
				ents = (char *)Mem_Alloc( host.mempool, lumplen + 1 );
				FS_Read( f, ents, lumplen );
			}

			if( ents )
			{
				// if there are entities to parse, a missing message key just
				// means there is no title, so clear the message string now
				char	token[2048];

				message[0] = 0;
				pfile = ents;

				while(( pfile = COM_ParseFile( pfile, token )) != NULL )
				{
					if( !Q_strcmp( token, "{" )) continue;
					else if(!Q_strcmp( token, "}" )) break;
					else if(!Q_strcmp( token, "message" ))
					{
						// get the message contents
						pfile = COM_ParseFile( pfile, message );
					}
					else if(!Q_strcmp( token, "mapversion" ))
					{
						// get the message contents
						pfile = COM_ParseFile( pfile, token );
						mapver = Q_atoi( token );
					}
				}
				Mem_Free( ents );
			}
		}

		if( f ) FS_Close(f);
		FS_FileBase( t->filenames[i], matchbuf );

		switch( ver )
		{
		case Q1BSP_VERSION:
			if( mapver == 220 ) Q_strncpy( buf, "Half-Life Alpha", sizeof( buf ));
			else Q_strncpy( buf, "Quake", sizeof( buf ));
			break;
		case HLBSP_VERSION:
			if( gearbox ) Q_strncpy( buf, "Blue-Shift", sizeof( buf ));
			else if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf ));
			else Q_strncpy( buf, "Half-Life", sizeof( buf ));
			break;
		case XTBSP_VERSION:
			if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf ));
			else Q_strncpy( buf, "Xash3D", sizeof( buf ));
			break;
		default:
			Q_strncpy( buf, "??", sizeof( buf ));
			break;
		}

		Msg( "%16s (%s) ^3%s^7\n", matchbuf, buf, message );
		nummaps++;
	}

	Msg( "\n^3 %i maps found.\n", nummaps );
	Mem_Free( t );

	// cut shortestMatch to the amount common with s
	for( i = 0; matchbuf[i]; i++ )
	{
		if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] ))
			completedname[i] = 0;
	}
	return true;
}
Exemple #12
0
/*
=================
Host_InitCommon
=================
*/
void Host_InitCommon( const char* moduleName, const char* cmdLine, const char *progname, qboolean bChangeGame )
{
	char		dev_level[4];
	char		szTemp[MAX_SYSPATH];
	string		szRootPath;
#ifdef _WIN32
	MEMORYSTATUS	lpBuffer;

	lpBuffer.dwLength = sizeof( MEMORYSTATUS );
	GlobalMemoryStatus( &lpBuffer );
#endif

#ifndef __ANDROID__
	if( !(SDL_GetBasePath()) )
		Sys_Error( "couldn't determine current directory" );

	Q_strncpy(host.rootdir, SDL_GetBasePath(), sizeof(host.rootdir));

	if( host.rootdir[Q_strlen( host.rootdir ) - 1] == '/' )
		host.rootdir[Q_strlen( host.rootdir ) - 1] = 0;
#else
	Q_strncpy(host.rootdir, GAMEPATH, sizeof(host.rootdir));
#endif

#ifdef _WIN32
	host.oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
	host.hInst = GetModuleHandle( NULL );
#endif
	host.change_game = bChangeGame;
	host.state = HOST_INIT; // initialzation started
	host.developer = host.old_developer = 0;

	CRT_Init(); // init some CRT functions

	// some commands may turn engine into infinity loop,
	// e.g. xash.exe +game xash -game xash
	// so we clearing all cmd_args, but leave dbg states as well
	if( cmdLine ) Sys_ParseCommandLine( cmdLine );
#ifdef _WIN32
	SetErrorMode( SEM_FAILCRITICALERRORS );	// no abort/retry/fail errors
#endif

	host.mempool = Mem_AllocPool( "Zone Engine" );

	if( Sys_CheckParm( "-console" )) host.developer = 1;
	if( Sys_CheckParm( "-dev" ))
	{
		if( Sys_GetParmFromCmdLine( "-dev", dev_level ))
		{
			if( Q_isdigit( dev_level ))
				host.developer = abs( Q_atoi( dev_level ));
			else host.developer++; // -dev == 1, -dev -console == 2
		}
		else host.developer++; // -dev == 1, -dev -console == 2
	}

	host.type = HOST_NORMAL; // predict state
	host.con_showalways = true;
#ifdef PANDORA
	if( Sys_CheckParm( "-noshouldermb" )) noshouldermb = 1;
#endif

#ifdef __ANDROID__
	if (chdir(host.rootdir) == 0)
		MsgDev(D_INFO,"%s is working directory now",host.rootdir);
	else
		MsgDev(D_ERROR,"%s is not exists",host.rootdir);
#else
	// we can specified custom name, from Sys_NewInstance
	if( SDL_GetBasePath() && !host.change_game )
	{
		Q_strncpy( szTemp, SDL_GetBasePath(), sizeof(szTemp) );
		FS_FileBase( szTemp, SI.ModuleName );
	}

	if(moduleName) Q_strncpy(SI.ModuleName, moduleName, sizeof(SI.ModuleName));

	FS_ExtractFilePath( SI.ModuleName, szRootPath );
	if( Q_stricmp( host.rootdir, szRootPath ))
	{
		Q_strncpy( host.rootdir, szRootPath, sizeof( host.rootdir ));
#ifdef _WIN32
		SetCurrentDirectory( host.rootdir );
#else
		chdir( host.rootdir );
#endif
	}
#endif

	if( SI.ModuleName[0] == '#' ) host.type = HOST_DEDICATED; 

	// determine host type
	if( progname[0] == '#' )
	{
		Q_strncpy( SI.ModuleName, progname + 1, sizeof( SI.ModuleName ));
		host.type = HOST_DEDICATED;
	}
	else Q_strncpy( SI.ModuleName, progname, sizeof( SI.ModuleName )); 

	if( host.type == HOST_DEDICATED )
	{
		// check for duplicate dedicated server
		host.hMutex = SDL_CreateMutex(  );

		if( !host.hMutex )
		{
			MSGBOX( "Dedicated server already running" );
			Sys_Quit();
			return;
		}

		Sys_MergeCommandLine( cmdLine );

		SDL_DestroyMutex( host.hMutex );
		host.hMutex = SDL_CreateSemaphore( 0 );
		if( host.developer < 3 ) host.developer = 3; // otherwise we see empty console
	}
	else
	{
		// don't show console as default
		if( host.developer < D_WARN ) host.con_showalways = false;
	}

	host.old_developer = host.developer;

	Con_CreateConsole();

	// first text message into console or log 
	MsgDev( D_NOTE, "Sys_LoadLibrary: Loading xash.dll - ok\n" );

	// startup cmds and cvars subsystem
	Cmd_Init();
	Cvar_Init();

	// share developer level across all dlls
	Q_snprintf( dev_level, sizeof( dev_level ), "%i", host.developer );
	Cvar_Get( "developer", dev_level, CVAR_INIT, "current developer level" );
	Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
	Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );

	FS_Init();
	Image_Init();
	Sound_Init();

	FS_LoadGameInfo( NULL );
	Q_strncpy( host.gamefolder, GI->gamefolder, sizeof( host.gamefolder ));


	if( GI->secure )
	{
		// clear all developer levels when game is protected
		Cvar_FullSet( "developer", "0", CVAR_INIT );
		host.developer = host.old_developer = 0;
		host.con_showalways = false;
	}

	HPAK_Init();

	IN_Init();
	Key_Init();
}
Exemple #13
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
================
*/
qboolean SV_SpawnServer( const char *mapname, const char *startspot )
{
	int	i, current_skill;
	qboolean	loadgame, paused;
	qboolean	background, changelevel;

	// save state
	loadgame = sv.loadgame;
	background = sv.background;
	changelevel = sv.changelevel;
	paused = sv.paused;

	if( sv.state == ss_dead )
		SV_InitGame(); // the game is just starting
	else if( !sv_maxclients->modified )
		Cmd_ExecuteString( "latch\n", src_command );
	else MsgDev( D_ERROR, "SV_SpawnServer: while 'maxplayers' was modified.\n" );

	sv_maxclients->modified = false;
	deathmatch->modified = false;
	teamplay->modified = false;
	coop->modified = false;

	if( !svs.initialized )
		return false;

	svgame.globals->changelevel = false; // will be restored later if needed
	svs.timestart = Sys_DoubleTime();
	svs.spawncount++; // any partially connected client will be restarted

	if( startspot )
	{
		MsgDev( D_INFO, "Spawn Server: %s [%s]\n", mapname, startspot );
	}
	else
	{
		MsgDev( D_INFO, "Spawn Server: %s\n", mapname );
	}

	sv.state = ss_dead;
	Host_SetServerState( sv.state );
	Q_memset( &sv, 0, sizeof( sv ));	// wipe the entire per-level structure

	// restore state
	sv.paused = paused;
	sv.loadgame = loadgame;
	sv.background = background;
	sv.changelevel = changelevel;
	sv.time = 1.0f;			// server spawn time it's always 1.0 second
	svgame.globals->time = sv.time;
	
	// initialize buffers
	BF_Init( &sv.datagram, "Datagram", sv.datagram_buf, sizeof( sv.datagram_buf ));
	BF_Init( &sv.reliable_datagram, "Datagram R", sv.reliable_datagram_buf, sizeof( sv.reliable_datagram_buf ));
	BF_Init( &sv.multicast, "Multicast", sv.multicast_buf, sizeof( sv.multicast_buf ));
	BF_Init( &sv.signon, "Signon", sv.signon_buf, sizeof( sv.signon_buf ));
	BF_Init( &sv.spectator_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));

	// leave slots at start for clients only
	for( i = 0; i < sv_maxclients->integer; i++ )
	{
		// needs to reconnect
		if( svs.clients[i].state > cs_connected )
			svs.clients[i].state = cs_connected;
	}

	// make cvars consistant
	if( Cvar_VariableInteger( "coop" )) Cvar_SetFloat( "deathmatch", 0 );
	current_skill = (int)(Cvar_VariableValue( "skill" ) + 0.5f);
	current_skill = bound( 0, current_skill, 3 );

	Cvar_SetFloat( "skill", (float)current_skill );

	if( sv.background )
	{
		// tell the game parts about background state
		Cvar_FullSet( "sv_background", "1", CVAR_READ_ONLY );
		Cvar_FullSet( "cl_background", "1", CVAR_READ_ONLY );
	}
	else
	{
		Cvar_FullSet( "sv_background", "0", CVAR_READ_ONLY );
		Cvar_FullSet( "cl_background", "0", CVAR_READ_ONLY );
	}

	// make sure what server name doesn't contain path and extension
	FS_FileBase( mapname, sv.name );

	if( startspot )
		Q_strncpy( sv.startspot, startspot, sizeof( sv.startspot ));
	else sv.startspot[0] = '\0';

	Q_snprintf( sv.model_precache[1], sizeof( sv.model_precache[0] ), "maps/%s.bsp", sv.name );
	Mod_LoadWorld( sv.model_precache[1], &sv.checksum, false );
	sv.worldmodel = Mod_Handle( 1 ); // get world pointer

	for( i = 1; i < sv.worldmodel->numsubmodels; i++ )
	{
		Q_sprintf( sv.model_precache[i+1], "*%i", i );
		Mod_RegisterModel( sv.model_precache[i+1], i+1 );
	}

	// precache and static commands can be issued during map initialization
	sv.state = ss_loading;

	Host_SetServerState( sv.state );

	// clear physics interaction links
	SV_ClearWorld();

	// tell dlls about new level started
	svgame.dllFuncs.pfnParmsNewLevel();

	return true;
}