示例#1
0
文件: cd.c 项目: Nekrofage/Quake2RPi
static void
CD_f ()
{
	char *command;
	int cdstate;

	if ( Cmd_Argc() < 2 )
	{
		return;
	}

	command = Cmd_Argv( 1 );

	if ( !Q_strcasecmp( command, "on" ) )
	{
		enabled = true;
	}

	if ( !Q_strcasecmp( command, "off" ) )
	{
		if ( !cd_id )
		{
			return;
		}

		cdstate = SDL_CDStatus( cd_id );

		if ( ( cdstate == CD_PLAYING ) || ( cdstate == CD_PAUSED ) )
		{
			CDAudio_Stop();
		}

		enabled = false;
		return;
	}

	if ( !Q_strcasecmp( command, "play" ) )
	{
		CDAudio_Play( (byte) atoi( Cmd_Argv( 2 ) ), false );
		return;
	}

	if ( !Q_strcasecmp( command, "loop" ) )
	{
		CDAudio_Play( (byte) atoi( Cmd_Argv( 2 ) ), true );
		return;
	}

	if ( !Q_strcasecmp( command, "stop" ) )
	{
		CDAudio_Stop();
		return;
	}

	if ( !Q_strcasecmp( command, "pause" ) )
	{
		CDAudio_Pause();
		return;
	}

	if ( !Q_strcasecmp( command, "resume" ) )
	{
		CDAudio_Resume();
		return;
	}

	if ( !Q_strcasecmp( command, "eject" ) )
	{
		CDAudio_Eject();
		return;
	}

	if ( !Q_strcasecmp( command, "info" ) )
	{
		if ( !cd_id )
		{
			return;
		}

		cdstate = SDL_CDStatus( cd_id );
		Com_Printf( "%d tracks\n", cd_id->numtracks );

		if ( cdstate == CD_PLAYING )
		{
			Com_Printf( "Currently %s track %d\n",
					playLooping ? "looping" : "playing",
					cd_id->cur_track + 1 );
		}
		else
		if ( cdstate == CD_PAUSED )
		{
			Com_Printf( "Paused %s track %d\n",
					playLooping ? "looping" : "playing",
					cd_id->cur_track + 1 );
		}

		return;
	}
}
示例#2
0
/*
===================
CL_GetServerCommand

Set up argc/argv for the given command
===================
*/
qboolean CL_GetServerCommand( int serverCommandNumber ) {
	char	*s;
	char	*cmd;
	static char bigConfigString[BIG_INFO_STRING];
	int argc;

	// if we have irretrievably lost a reliable command, drop the connection
	if ( serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS ) {
		// when a demo record was started after the client got a whole bunch of
		// reliable commands then the client never got those first reliable commands
		if ( clc.demoplaying )
			return qfalse;
		Com_Error( ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out" );
		return qfalse;
	}

	if ( serverCommandNumber > clc.serverCommandSequence ) {
		Com_Error( ERR_DROP, "CL_GetServerCommand: requested a command not received" );
		return qfalse;
	}

	s = clc.serverCommands[ serverCommandNumber & ( MAX_RELIABLE_COMMANDS - 1 ) ];
	clc.lastExecutedServerCommand = serverCommandNumber;

	Com_DPrintf( "serverCommand: %i : %s\n", serverCommandNumber, s );

rescan:
	Cmd_TokenizeString( s );
	cmd = Cmd_Argv(0);
	argc = Cmd_Argc();

	if ( !strcmp( cmd, "disconnect" ) ) {
		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=552
		// allow server to indicate why they were disconnected
		if ( argc >= 2 )
			Com_Error( ERR_SERVERDISCONNECT, "Server disconnected - %s", Cmd_Argv( 1 ) );
		else
			Com_Error( ERR_SERVERDISCONNECT, "Server disconnected" );
	}

	if ( !strcmp( cmd, "bcs0" ) ) {
		Com_sprintf( bigConfigString, BIG_INFO_STRING, "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2) );
		return qfalse;
	}

	if ( !strcmp( cmd, "bcs1" ) ) {
		s = Cmd_Argv(2);
		if( strlen(bigConfigString) + strlen(s) >= BIG_INFO_STRING ) {
			Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" );
		}
		strcat( bigConfigString, s );
		return qfalse;
	}

	if ( !strcmp( cmd, "bcs2" ) ) {
		s = Cmd_Argv(2);
		if( strlen(bigConfigString) + strlen(s) + 1 >= BIG_INFO_STRING ) {
			Com_Error( ERR_DROP, "bcs exceeded BIG_INFO_STRING" );
		}
		strcat( bigConfigString, s );
		strcat( bigConfigString, "\"" );
		s = bigConfigString;
		goto rescan;
	}

	if ( !strcmp( cmd, "cs" ) ) {
		CL_ConfigstringModified();
		// reparse the string, because CL_ConfigstringModified may have done another Cmd_TokenizeString()
		Cmd_TokenizeString( s );
		return qtrue;
	}

	if ( !strcmp( cmd, "map_restart" ) ) {
		// clear notify lines and outgoing commands before passing
		// the restart to the cgame
		Con_ClearNotify();
		// reparse the string, because Con_ClearNotify() may have done another Cmd_TokenizeString()
		Cmd_TokenizeString( s );
		Com_Memset( cl.cmds, 0, sizeof( cl.cmds ) );
		return qtrue;
	}

	// the clientLevelShot command is used during development
	// to generate 128*128 screenshots from the intermission
	// point of levels for the menu system to use
	// we pass it along to the cgame to make apropriate adjustments,
	// but we also clear the console and notify lines here
	if ( !strcmp( cmd, "clientLevelShot" ) ) {
		// don't do it if we aren't running the server locally,
		// otherwise malicious remote servers could overwrite
		// the existing thumbnails
		if ( !com_sv_running->integer ) {
			return qfalse;
		}
		// close the console
		Con_Close();
		// take a special screenshot next frame
		Cbuf_AddText( "wait ; wait ; wait ; wait ; screenshot levelshot\n" );
		return qtrue;
	}

	// we may want to put a "connect to other server" command here

	// cgame can now act on the command
	return qtrue;
}
示例#3
0
/*
============
Cmd_ArgvBuffer

The interpreted versions use this because
they can't have pointers returned to them
============
*/
void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength )
{
	Q_strncpyz( buffer, Cmd_Argv( arg ), bufferLength );
}
示例#4
0
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f(void)
{
	int         i;
	client_t    *client;
	char        *denied;
	qboolean    isBot;
	int         delay = 0;
	gamestate_t new_gs, old_gs;     // NERVE - SMF

	// make sure we aren't restarting twice in the same frame
	if (com_frameTime == sv.serverId)
	{
		return;
	}

	// make sure server is running
	if (!com_sv_running->integer)
	{
		Com_Printf("Server is not running.\n");
		return;
	}

	// ydnar: allow multiple delayed server restarts [atvi bug 3813]
	//%	if ( sv.restartTime ) {
	//%		return;
	//%	}

	if (Cmd_Argc() > 1)
	{
		delay = atoi(Cmd_Argv(1));
	}

	if (delay)
	{
		sv.restartTime = svs.time + delay * 1000;
		SV_SetConfigstring(CS_WARMUP, va("%i", sv.restartTime));
		return;
	}

	// NERVE - SMF - read in gamestate or just default to GS_PLAYING
	old_gs = atoi(Cvar_VariableString("gamestate"));

	if (SV_GameIsSinglePlayer() || SV_GameIsCoop())
	{
		new_gs = GS_PLAYING;
	}
	else
	{
		if (Cmd_Argc() > 2)
		{
			new_gs = atoi(Cmd_Argv(2));
		}
		else
		{
			new_gs = GS_PLAYING;
		}
	}

	if (!SV_TransitionGameState(new_gs, old_gs, delay))
	{
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if (sv_maxclients->modified)
	{
		char mapname[MAX_QPATH];

		Com_Printf("sv_maxclients variable change -- restarting.\n");
		// restart the map the slow way
		Q_strncpyz(mapname, Cvar_VariableString("mapname"), sizeof(mapname));

		SV_SpawnServer(mapname, qfalse);
		return;
	}

	// Check for loading a saved game
	if (Cvar_VariableIntegerValue("savegame_loading"))
	{
		// open the current savegame, and find out what the time is, everything else we can ignore
		char savemap[MAX_QPATH];
		byte *buffer;
		int  size, savegameTime;
		char *cl_profileStr = Cvar_VariableString("cl_profile");

		if (com_gameInfo.usesProfiles)
		{
			Com_sprintf(savemap, sizeof(savemap), "profiles/%s/save/current.sav", cl_profileStr);
		}
		else
		{
			Q_strncpyz(savemap, "save/current.sav", sizeof(savemap));
		}

		size = FS_ReadFile(savemap, NULL);
		if (size < 0)
		{
			Com_Printf("Can't find savegame %s\n", savemap);
			return;
		}

		//buffer = Hunk_AllocateTempMemory(size);
		FS_ReadFile(savemap, (void **)&buffer);

		// the mapname is at the very start of the savegame file
		savegameTime = *( int * )(buffer + sizeof(int) + MAX_QPATH);

		if (savegameTime >= 0)
		{
			svs.time = savegameTime;
		}

		Hunk_FreeTempMemory(buffer);
	}
	// done.

	// toggle the server bit so clients can detect that a
	// map_restart has happened
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// generate a new serverid
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set("sv_serverid", va("%i", sv.serverId));

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state      = SS_LOADING;
	sv.restarting = qtrue;

	Cvar_Set("sv_serverRestarting", "1");

	SV_RestartGameProgs();

	// run a few frames to allow everything to settle
	for (i = 0; i < GAME_INIT_FRAMES; i++)
	{
		VM_Call(gvm, GAME_RUN_FRAME, svs.time);
		svs.time += FRAMETIME;
	}

	// create a baseline for more efficient communications
	// Gordon: meh, this wont work here as the client doesn't know it has happened
//	SV_CreateBaseline ();

	sv.state      = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for (i = 0 ; i < sv_maxclients->integer ; i++)
	{
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if (client->state < CS_CONNECTED)
		{
			continue;
		}

		if (client->netchan.remoteAddress.type == NA_BOT)
		{
			if (SV_GameIsSinglePlayer() || SV_GameIsCoop())
			{
				continue;   // dont carry across bots in single player
			}
			isBot = qtrue;
		}
		else
		{
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand(client, "map_restart\n");

		// connect the client again, without the firstTime flag
		denied = VM_ExplicitArgPtr(gvm, VM_Call(gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot));
		if (denied)
		{
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient(client, denied);
			if ((!SV_GameIsSinglePlayer()) || (!isBot))
			{
				Com_Printf("SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i);   // bk010125
			}
			continue;
		}

		client->state = CS_ACTIVE;

		SV_ClientEnterWorld(client, &client->lastUsercmd);
	}

	// run another frame to allow things to look at all the players
	VM_Call(gvm, GAME_RUN_FRAME, svs.time);
	svs.time += FRAMETIME;

	Cvar_Set("sv_serverRestarting", "0");
}
示例#5
0
文件: servers.c 项目: m4son/q2pro
static void ParseMasterArgs(netadr_t *broadcast)
{
    void *data;
    ssize_t len;
    void (*parse)(void *, size_t, size_t);
    size_t chunk;
    char *s, *p;
    int i, argc;

    Cmd_TokenizeString(m_servers.args, qfalse);

    argc = Cmd_Argc();
    if (!argc) {
        // default action to take when no URLs are given
        ParseAddressBook();
        broadcast->type = NA_BROADCAST;
        broadcast->port = BigShort(PORT_SERVER);
        return;
    }

    for (i = 0; i < argc; i++) {
        s = Cmd_Argv(i);
        if (!*s)
            continue;

        // parse binary format specifier
        parse = ParsePlain;
        chunk = 0;
        if (*s == '+' || *s == '-') {
            parse = ParseBinary;
            chunk = strtoul(s, &p, 10);
            if (s == p) {
                chunk = 6;
                s = p + 1;
            } else {
                if (chunk < 6)
                    goto ignore;
                s = p;
            }
        }

        if (!strncmp(s, "file://", 7)) {
            len = FS_LoadFile(s + 7, &data);
            if (len < 0)
                continue;
            (*parse)(data, len, chunk);
            FS_FreeFile(data);
            continue;
        }

        if (!strncmp(s, "http://", 7)) {
#if USE_CURL
            len = HTTP_FetchFile(s + 7, &data);
            if (len < 0)
                continue;
            (*parse)(data, len, chunk);
            Z_Free(data);
#else
            Com_Printf("Can't fetch '%s', no HTTP support compiled in.\n", s);
#endif
            continue;
        }

        if (!strncmp(s, "favorites://", 12)) {
            ParseAddressBook();
            continue;
        }

        if (!strncmp(s, "broadcast://", 12)) {
            broadcast->type = NA_BROADCAST;
            broadcast->port = BigShort(PORT_SERVER);
            continue;
        }

        if (!strncmp(s, "quake2://", 9)) {
            AddServer(NULL, s + 9);
            continue;
        }

ignore:
        Com_Printf("Ignoring invalid master URL: %s\n", s);
    }
}
static void SV_DelBanFromList(qboolean isexception)
{
	int index, count = 0, todel, mask;
	netadr_t ip;
	char *banstring;
	
	if(Cmd_Argc() != 2)
	{
		Com_Printf ("Usage: %s (ip[/subnet] | num)\n", Cmd_Argv(0));
		return;
	}

	banstring = Cmd_Argv(1);
	
	if(strchr(banstring, '.') || strchr(banstring, ':'))
	{
		serverBan_t *curban;
		
		if(SV_ParseCIDRNotation(&ip, &mask, banstring))
		{
			Com_Printf("Error: Invalid address %s\n", banstring);
			return;
		}
		
		index = 0;
		
		while(index < serverBansCount)
		{
			curban = &serverBans[index];
			
			if(curban->isexception == isexception		&&
			   curban->subnet >= mask 			&&
			   NET_CompareBaseAdrMask(curban->ip, ip, mask))
			{
				Com_Printf("Deleting %s %s/%d\n",
					   isexception ? "exception" : "ban",
					   NET_AdrToString(curban->ip), curban->subnet);
					   
				SV_DelBanEntryFromList(index);
			}
			else
				index++;
		}
	}
	else
	{
		todel = atoi(Cmd_Argv(1));

		if(todel < 1 || todel > serverBansCount)
		{
			Com_Printf("Error: Invalid ban number given\n");
			return;
		}
	
		for(index = 0; index < serverBansCount; index++)
		{
			if(serverBans[index].isexception == isexception)
			{
				count++;
			
				if(count == todel)
				{
					Com_Printf("Deleting %s %s/%d\n",
					   isexception ? "exception" : "ban",
					   NET_AdrToString(serverBans[index].ip), serverBans[index].subnet);

					SV_DelBanEntryFromList(index);

					break;
				}
			}
		}
	}
	
	SV_WriteBans();
}
示例#7
0
文件: cmd.c 项目: feraligatr/wolf2d
/*
-----------------------------------------------------------------------------
 Function: Cmd_Alias_f -Creates a new command that executes a command 
						string (possibly ; seperated).
 
 Parameters: Nothing.
 
 Returns: Nothing. 
 
 Notes: 

-----------------------------------------------------------------------------
*/
PRIVATE void Cmd_Alias_f( void )
{
	cmdalias_t	*a;
	char		cmd[ 1024 ];
	int			i, c;
	char		*s;
	W32	hashid;

	if( Cmd_Argc() == 1 )
	{
		Com_Printf( "Current alias commands:\n" );
		for( a = cmd_alias ; a ; a = a->next )
		{
			Com_Printf( "%s : %s\n", a->name, a->value );
		}
		return;
	}

	s = Cmd_Argv( 1 );
	if( strlen( s ) >= MAX_ALIAS_NAME )
	{
		Com_Printf( "Alias name is too long\n" );
		return;
	}

	hashid = my_strhash( s );

	// if the alias already exists, reuse it
	for( a = cmd_alias ; a ; a = a->next )
	{
		if( hashid == a->id )
		{
			Z_Free( a->value );
			break;
		}
	}

	if( ! a )
	{
		a = Z_Malloc( sizeof( cmdalias_t ) );
		a->next = cmd_alias;
		cmd_alias = a;
	}	
	my_strlcpy( a->name, s, sizeof( a->name ) );
	a->id = hashid;

// copy the rest of the command line
	cmd[ 0 ] = '\0';	// start out with a NUL-terminated string
	c = Cmd_Argc();
	for( i = 2; i < c; ++i )
	{
		my_strlcat( cmd, Cmd_Argv( i ), sizeof( cmd ) );
		if( i != (c - 1) )
		{
			my_strlcat( cmd, " ", sizeof( cmd ) );
		}
	}
	my_strlcat( cmd, "\n", sizeof( cmd ) );
	
	a->value = my_CopyString( cmd );
}
示例#8
0
void
KeyUp(kbutton_t *b)
{
	int k;
	char *c;
	unsigned uptime;

	c = Cmd_Argv(1);

	if (c[0])
	{
		k = (int)strtol(c, (char **)NULL, 10);
	}

	else
	{
		/* typed manually at the console, assume for unsticking, so clear all */
		b->down[0] = b->down[1] = 0;
		b->state = 4; /* impulse up */
		return;
	}

	if (b->down[0] == k)
	{
		b->down[0] = 0;
	}

	else if (b->down[1] == k)
	{
		b->down[1] = 0;
	}

	else
	{
		return; /* key up without coresponding down (menu pass through) */
	}

	if (b->down[0] || b->down[1])
	{
		return; /* some other key is still holding it down */
	}

	if (!(b->state & 1))
	{
		return; /* still up (this should not happen) */
	}

	/* save timestamp */
	c = Cmd_Argv(2);
	uptime = (int)strtol(c, (char **)NULL, 10);

	if (uptime)
	{
		b->msec += uptime - b->downtime;
	}

	else
	{
		b->msec += 10;
	}

	b->state &= ~1; /* now up */
	b->state |= 4; /* impulse up */
}
示例#9
0
void
IN_Impulse(void)
{
	in_impulse = (int)strtol(Cmd_Argv(1), (char **)NULL, 10);
}
示例#10
0
文件: cl_demo.c 项目: Reedych/xash3d
/*
====================
CL_PlayDemo_f

playdemo <demoname>
====================
*/
void CL_PlayDemo_f( void )
{
	string	filename;
	string	demoname;
	int	i;

	if( Cmd_Argc() != 2 )
	{
		Msg( "Usage: playdemo <demoname>\n" );
		return;
	}

	if( cls.demoplayback )
	{
		CL_StopPlayback();
	}

	if( cls.demorecording )
	{
		Msg( "Can't playback during demo record.\n");
		return;
	}

	Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ) - 1 );
	Q_snprintf( filename, sizeof( filename ), "demos/%s.dem", demoname );

	if( !FS_FileExists( filename, true ))
	{
		MsgDev( D_ERROR, "couldn't open %s\n", filename );
		cls.demonum = -1; // stop demo loop
		return;
	}

	cls.demofile = FS_Open( filename, "rb", true );
	Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname ));
	Q_strncpy( menu.globals->demoname, demoname, sizeof( menu.globals->demoname ));

	// read in the m_DemoHeader
	FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));

	if( demo.header.id != IDEMOHEADER )
	{
		MsgDev( D_ERROR, "%s is not a demo file\n", filename );
		FS_Close( cls.demofile );
		cls.demofile = NULL;
		cls.demonum = -1; // stop demo loop
		return;
	}

	if( demo.header.net_protocol != PROTOCOL_VERSION || demo.header.dem_protocol != DEMO_PROTOCOL )
	{
		MsgDev( D_ERROR, "demo protocol outdated\n"
			"Demo file protocols Network(%i), Demo(%i)\n"
			"Server protocol is at Network(%i), Demo(%i)\n",
			demo.header.net_protocol, 
			demo.header.dem_protocol,
			PROTOCOL_VERSION,
			DEMO_PROTOCOL
		);

		FS_Close( cls.demofile );
		cls.demofile = NULL;
		cls.demonum = -1; // stop demo loop
		return;
	}

	// now read in the directory structure.
	FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
	FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));

	if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
	{
		MsgDev( D_ERROR, "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
		FS_Close( cls.demofile );
		cls.demofile = NULL;
		cls.demonum = -1; // stop demo loop
		cls.changedemo = false;
		return;
	}

	if( cls.changedemo )
	{
		S_StopAllSounds();
		SCR_BeginLoadingPlaque( false );

		CL_ClearState ();
		CL_InitEdicts (); // re-arrange edicts
	}
	else
	{
		// NOTE: at this point demo is still valid
		CL_Disconnect();
		Host_ShutdownServer();

		Con_Close();
		UI_SetActiveMenu( false );
	}

	// allocate demo entries
	demo.directory.entries = Mem_Alloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );

	for( i = 0; i < demo.directory.numentries; i++ )
	{
		FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
	}

	demo.entryIndex = 0;
	demo.entry = &demo.directory.entries[demo.entryIndex];

	FS_Seek( cls.demofile, demo.entry->offset, SEEK_SET );

	cls.demoplayback = true;
	cls.state = ca_connected;
	cl.background = (cls.demonum != -1) ? true : false;

	demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message

	Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, net_qport->integer );

	demo.framecount = 0;
	cls.lastoutgoingcommand = -1;
 	cls.nextcmdtime = host.realtime;

	// g-cont. is this need?
	Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));

	// begin a playback demo
}
示例#11
0
文件: cl_demo.c 项目: Reedych/xash3d
/*
====================
CL_Record_f

record <demoname>
Begins recording a demo from the current position
====================
*/
void CL_Record_f( void )
{
	const char	*name;
	string		demoname, demopath, demoshot;
	int		n;

	if( Cmd_Argc() == 1 )
	{
		name = "new";
	}
	else if( Cmd_Argc() == 2 )
	{
		name = Cmd_Argv( 1 );
	}
	else
	{
		Msg( "Usage: record <demoname>\n" );
		return;
	}

	if( cls.demorecording )
	{
		Msg( "Already recording.\n");
		return;
	}

	if( cls.demoplayback )
	{
		Msg( "Can't record during demo playback.\n");
		return;
	}

	if( !cls.demoheader || cls.state != ca_active )
	{
		Msg( "You must be in a level to record.\n");
		return;
	}

	if( !Q_stricmp( name, "new" ))
	{
		// scan for a free filename
		for( n = 0; n < 10000; n++ )
		{
			CL_DemoGetName( n, demoname );
			if( !FS_FileExists( va( "demos/%s.dem", demoname ), true ))
				break;
		}

		if( n == 10000 )
		{
			Msg( "^3ERROR: no free slots for demo recording\n" );
			return;
		}
	}
	else Q_strncpy( demoname, name, sizeof( demoname ));

	// open the demo file
	Q_sprintf( demopath, "demos/%s.dem", demoname );
	Q_sprintf( demoshot, "demos/%s.bmp", demoname );

	// make sure what old demo is removed
	if( FS_FileExists( demopath, false )) FS_Delete( demopath );
	if( FS_FileExists( demoshot, false )) FS_Delete( demoshot );

	// write demoshot for preview
	Cbuf_AddText( va( "demoshot \"%s\"\n", demoname ));
	Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname ));
	Q_strncpy( menu.globals->demoname, demoname, sizeof( menu.globals->demoname ));
	
	CL_WriteDemoHeader( demopath );
}
示例#12
0
/*
==================
SVC_DirectConnect

A connection request that did not come from the master
==================
*/
void SVC_DirectConnect (void)
{
    char		userinfo[MAX_INFO_STRING];
    netadr_t	adr;
    int32_t			i;
    client_t	*cl, *newcl;
    client_t	temp;
    edict_t		*ent;
    int32_t			edictnum;
    int32_t			version;
    int32_t			qport;
    int32_t			challenge;
    int32_t			previousclients;	// rich: connection limit per IP

    adr = net_from;

    Com_DPrintf ("SVC_DirectConnect ()\n");

    version = atoi(Cmd_Argv(1));
    if (version != PROTOCOL_VERSION)
    {
        Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is version %4.2f.\n", VERSION);
        Com_DPrintf ("    rejected connect from version %i\n", version);
        return;
    }

    qport = atoi(Cmd_Argv(2));

    challenge = atoi(Cmd_Argv(3));

    // r1ch: limit connections from a single IP
    previousclients = 0;
    for (i=0,cl=svs.clients; i<(int32_t)maxclients->value; i++,cl++)
    {
        if (cl->state == cs_free)
            continue;
        if (NET_CompareBaseAdr (adr, cl->netchan.remote_address))
        {
            // r1ch: zombies are less dangerous
            if (cl->state == cs_zombie)
                previousclients++;
            else
                previousclients += 2;
        }
    }
    if (previousclients >= (int32_t)sv_iplimit->value * 2)
    {
        Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nToo many connections from your host.\n");
        Com_DPrintf ("    too many connections\n");
        return;
    }
    // end r1ch fix

    strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-1);
    userinfo[sizeof(userinfo) - 1] = 0;

    // force the IP key/value pair so the game can filter based on ip
    Info_SetValueForKey (userinfo, "ip", NET_AdrToString(net_from));

    // attractloop servers are ONLY for local clients
    if (sv.attractloop)
    {
        if (!NET_IsLocalAddress (adr))
        {
            Com_Printf ("Remote connect in attract loop.  Ignored.\n");
            Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n");
            return;
        }
    }

    // see if the challenge is valid
    if (!NET_IsLocalAddress (adr))
    {
        for (i=0 ; i<MAX_CHALLENGES ; i++)
        {
            if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
            {
                if (challenge == svs.challenges[i].challenge)
                    break;		// good
                Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nBad challenge.\n");
                return;
            }
        }
        if (i == MAX_CHALLENGES)
        {
            Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nNo challenge for address.\n");
            return;
        }
    }

    newcl = &temp;
    memset (newcl, 0, sizeof(client_t));

    // if there is already a slot for this ip, reuse it
    for (i=0,cl=svs.clients ; i<maxclients->value ; i++,cl++)
    {
        if (cl->state == cs_free)
            continue;
        if (NET_CompareBaseAdr (adr, cl->netchan.remote_address)
                && ( cl->netchan.qport == qport
                     || adr.port == cl->netchan.remote_address.port ) )
        {
            if (!NET_IsLocalAddress (adr) && (svs.realtime - cl->lastconnect) < ((int32_t)sv_reconnect_limit->value * 1000))
            {
                Com_DPrintf ("%s:reconnect rejected : too soon\n", NET_AdrToString (adr));
                return;
            }
            // r1ch: !! fix nasty bug where non-disconnected clients (from dropped disconnect
            // packets) could be overwritten!
            if (cl->state != cs_zombie)
            {
                Com_DPrintf ("    client already found\n");
                // If we legitly get here, spoofed udp isn't possible (passed challenge) and client addr/port combo
                // is exactly the same, so we can assume its really a dropped/crashed client. i hope...
                Com_Printf ("Dropping %s, ghost reconnect\n", cl->name);
                SV_DropClient (cl);
            }
            // end r1ch fix

            Com_Printf ("%s:reconnect\n", NET_AdrToString (adr));

            SV_CleanClient (cl);	// r1ch: clean up last client data

            newcl = cl;
            goto gotnewcl;
        }
    }

    // find a client slot
    newcl = NULL;
    for (i=0,cl=svs.clients ; i<maxclients->value ; i++,cl++)
    {
        if (cl->state == cs_free)
        {
            newcl = cl;
            break;
        }
    }
    if (!newcl)
    {
        Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is full.\n");
        Com_DPrintf ("Rejected a connection.\n");
        return;
    }

gotnewcl:
    // build a new connection
    // accept the new client
    // this is the only place a client_t is ever initialized
    *newcl = temp;
    sv_client = newcl;
    edictnum = (newcl-svs.clients)+1;
    ent = EDICT_NUM(edictnum);
    newcl->edict = ent;
    newcl->challenge = challenge; // save challenge for checksumming

    // get the game a chance to reject this connection or modify the userinfo
    if (!(ge->ClientConnect (ent, userinfo)))
    {
        if (*Info_ValueForKey (userinfo, "rejmsg"))
            Netchan_OutOfBandPrint (NS_SERVER, adr, "print\n%s\nConnection refused.\n",
                                    Info_ValueForKey (userinfo, "rejmsg"));
        else
            Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n" );
        Com_DPrintf ("Game rejected a connection.\n");
        return;
    }

    // parse some info from the info strings
    strncpy (newcl->userinfo, userinfo, sizeof(newcl->userinfo)-1);
    SV_UserinfoChanged (newcl);

    // send the connect packet to the client
    Netchan_OutOfBandPrint (NS_SERVER, adr, "client_connect");

    Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport);

    newcl->state = cs_connected;

    SZ_Init (&newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf) );
    newcl->datagram.allowoverflow = true;
    newcl->lastmessage = svs.realtime;	// don't timeout
    newcl->lastconnect = svs.realtime;
}
示例#13
0
void CL_Say_f (void)
{
	char output[8192];
	char string[256];
	char *msg;
	int c;
	output[0] = '\0';
	if (cls.state == ca_disconnected || cls.demoplayback)
	{
#ifndef CLIENT_ONLY
		if (sv.state)
			SV_ConSay_f();
		else
#endif
			Con_TPrintf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
		return;
	}

	if (!strcmp("sayone", Cmd_Argv(0)))
	{
		if (strcmp(Info_ValueForKey(cl.serverinfo, "*distrib"), DISTRIBUTION) || atoi(Info_ValueForKey(cl.serverinfo, "*ver")) < PRE_SAYONE)
		{
			Con_Printf ("%s is only available with server support\n", Cmd_Argv(0));
			return;
		}
	}

	Q_strncpyz(output, Cmd_Argv(0), sizeof(string));
	for (msg = output; *msg; msg++)
		if (*msg >= 'A' && *msg <= 'Z')
			*msg = *msg - 'A' + 'a';

	msg = Cmd_Args();

	if (Cmd_Argc() > 1)
	{
		Q_strncatz(output, " \"", sizeof(output));

		while(*msg)
		{
			c = *msg;

			if (c == '%')
			{
				char *message = NULL;
				msg++;

				if (message == NULL)
				switch(*msg)
				{
				case 'n':
					Q_strncatz(output, name.string, sizeof(output));
					msg++;
					continue;
				case 'h':
					Q_strncatz(output, va("%i", cl.stats[0][STAT_HEALTH]), sizeof(output));
					msg++;
					continue;
				case 'a':
					Q_strncatz(output, va("%i", cl.stats[0][STAT_ARMOR]), sizeof(output));
					msg++;
					continue;
				case 'A':
					Q_strncatz(output, TP_ArmourType(), sizeof(output));
					msg++;
					continue;
				case 'l':
					Q_strncatz(output, CL_LocationName(cl.simorg[0]), sizeof(output));
					msg++;
					continue;
				case 'S':
					Q_strncatz(output, TP_ClassForTFSkin(), sizeof(output));
					msg++;
					continue;
				case '%':
					c  = '%';
					break;
				default:
					c  = '%';
					msg--;
					break;
				}
			}
			else if (c == '$')
			{
				msg++;
				switch(*msg)
				{
				case '\\': c = 0x0D; break;
				case ':': c = 0x0A; break;
				case '[': c = 0x10; break;
				case ']': c = 0x11; break;
				case 'G': c = 0x86; break;
				case 'R': c = 0x87; break;
				case 'Y': c = 0x88; break;
				case 'B': c = 0x89; break;
				case '(': c = 0x80; break;
				case '=': c = 0x81; break;
				case ')': c = 0x82; break;
				case 'a': c = 0x83; break;
				case '<': c = 0x1d; break;
				case '-': c = 0x1e; break;
				case '>': c = 0x1f; break;
				case ',': c = 0x1c; break;
				case '.': c = 0x9c; break;
				case 'b': c = 0x8b; break;
				case 'c':
				case 'd': c = 0x8d; break;
				case '$': c = '$'; break;
				case '^': c = '^'; break;
				case 'x':
					c = INVIS_CHAR1;
					break;
				case 'y':
					c = INVIS_CHAR2;
					break;
				case 'z':
					c = INVIS_CHAR3;
					break;
				default:
					msg--;
					break;
				}

			}
		
			Q_strncatz(output, va("%c", c), sizeof(output));

			msg++;
		}
		Q_strncatz(output, "\"", sizeof(output));
	}

	CL_SendClientCommand("%s", output);
}
示例#14
0
/* <18d23> ../engine/cvar.c:671 */
void Cmd_CvarList_f(void)
{
	cvar_t *var;
	int iCvars;
	int iArgs;
	const char *partial, *arg1;
	int ipLen;
	qboolean bAOnly;
	qboolean bSOnly;
	char szTemp[MAX_PATH];
	FileHandle_t f;
	FileHandle_t fp;
	qboolean bLogging;

	iCvars = 0;
	partial = NULL;
	bAOnly = FALSE;
	bSOnly = FALSE;
	f = NULL;
	fp = NULL;
	bLogging = FALSE;

	iArgs = Cmd_Argc();
	if (iArgs > 1)
	{
		arg1 = Cmd_Argv(1);

		if (!Q_stricmp(arg1, "?"))
		{
			Con_Printf("CvarList           : List all cvars\nCvarList [Partial] : List cvars starting with 'Partial'\nCvarList log [Partial] : Logs cvars to file \"cvarlist.txt\" in the gamedir.\n");
			return;
		}

		if (!Q_stricmp(arg1, "log"))
		{
			// Open log
			int i;
			for (i = 0; i < 100; i++)
			{
				Q_snprintf(szTemp, ARRAYSIZE(szTemp) - 1, "cvarlist%02d.txt", i);
				szTemp[ARRAYSIZE(szTemp) - 1] = 0;

				fp = FS_Open(szTemp, "r");
				if (!fp)
				{
					break;
				}
				FS_Close(fp);
			}

			if (i >= 100)
			{
				Con_Printf("Can't cvarlist! Too many existing cvarlist output files in the gamedir!\n");
				return;
			}

			f = FS_Open(szTemp, "wt");
			if (!f)
			{
				Con_Printf("Couldn't open \"%s\" for writing!\n", szTemp);
				return;
			}
			bLogging = TRUE;

			// Get next argument into partial, if present
			if (iArgs > 2)
			{
				partial = Cmd_Argv(2);
				ipLen = Q_strlen(partial);
			}
		}
		else if (!Q_stricmp(arg1, "-a"))
		{
			bAOnly = TRUE;
		}
		else if (!Q_stricmp(arg1, "-s"))
		{
			bSOnly = TRUE;
		}
		else
		{
			partial = arg1;
			ipLen = Q_strlen(partial);
		}
	}

	// Print cvars
	Con_Printf("CVar List\n--------------\n");

	for (var = cvar_vars; var; var = var->next)
	{
		if (bAOnly && !(var->flags & FCVAR_ARCHIVE))
		{
			continue;
		}
		if (bSOnly && !(var->flags & FCVAR_SERVER))
		{
			continue;
		}
		if (partial && Q_strnicmp(var->name, partial, ipLen))
		{
			continue;
		}

		Cmd_CvarListPrintCvar(var, f);
		iCvars++;
	}

	if (partial && *partial)
	{
		Con_Printf("--------------\n%3i CVars for [%s]\nCvarList ? for syntax\n", iCvars, partial);
	}
	else
	{
		Con_Printf("--------------\n%3i Total CVars\nCvarList ? for syntax\n", iCvars);
	}

	// Close log
	if (bLogging)
	{
		FS_Close(f);
		Con_Printf("cvarlist logged to %s\n", szTemp);
	}
}
/*
================
SV_MapRestart_f

Completely restarts a level, but doesn't send a new gamestate to the clients.
This allows fair starts with variable load times.
================
*/
static void SV_MapRestart_f( void ) {
	int			i;
	client_t	*client;
	char		*denied;
	qboolean	isBot;
	int			delay;

	// make sure we aren't restarting twice in the same frame
	if ( com_frameTime == sv.serverId ) {
		return;
	}

	// make sure server is running
	if ( !com_sv_running->integer ) {
		Com_Printf( "Server is not running.\n" );
		return;
	}

	if ( sv.restartTime ) {
		return;
	}

	if (Cmd_Argc() > 1 ) {
		delay = atoi( Cmd_Argv(1) );
	}
	else {
		delay = 5;
	}
	if( delay && !Cvar_VariableValue("g_doWarmup") ) {
		sv.restartTime = sv.time + delay * 1000;
		SV_SetConfigstring( CS_WARMUP, va("%i", sv.restartTime) );
		return;
	}

	// check for changes in variables that can't just be restarted
	// check for maxclients change
	if ( sv_maxclients->modified || sv_gametype->modified ) {
		char	mapname[MAX_QPATH];

		Com_Printf( "variable change -- restarting.\n" );
		// restart the map the slow way
		Q_strncpyz( mapname, Cvar_VariableString( "mapname" ), sizeof( mapname ) );

		SV_SpawnServer( mapname, qfalse );
		return;
	}

	// toggle the server bit so clients can detect that a
	// map_restart has happened
	svs.snapFlagServerBit ^= SNAPFLAG_SERVERCOUNT;

	// generate a new serverid	
	// TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart
	sv.serverId = com_frameTime;
	Cvar_Set( "sv_serverid", va("%i", sv.serverId ) );

	// if a map_restart occurs while a client is changing maps, we need
	// to give them the correct time so that when they finish loading
	// they don't violate the backwards time check in cl_cgame.c
	for (i=0 ; i<sv_maxclients->integer ; i++) {
		if (svs.clients[i].state == CS_PRIMED) {
			svs.clients[i].oldServerTime = sv.restartTime;
		}
	}

	// reset all the vm data in place without changing memory allocation
	// note that we do NOT set sv.state = SS_LOADING, so configstrings that
	// had been changed from their default values will generate broadcast updates
	sv.state = SS_LOADING;
	sv.restarting = qtrue;

	SV_RestartGameProgs();

	// run a few frames to allow everything to settle
	for (i = 0; i < 3; i++)
	{
		VM_Call (gvm, GAME_RUN_FRAME, sv.time);
		sv.time += 100;
		svs.time += 100;
	}

	sv.state = SS_GAME;
	sv.restarting = qfalse;

	// connect and begin all the clients
	for (i=0 ; i<sv_maxclients->integer ; i++) {
		client = &svs.clients[i];

		// send the new gamestate to all connected clients
		if ( client->state < CS_CONNECTED) {
			continue;
		}

		if ( client->netchan.remoteAddress.type == NA_BOT ) {
			isBot = qtrue;
		} else {
			isBot = qfalse;
		}

		// add the map_restart command
		SV_AddServerCommand( client, "map_restart\n" );

		// connect the client again, without the firstTime flag
		denied = VM_ExplicitArgPtr( gvm, VM_Call( gvm, GAME_CLIENT_CONNECT, i, qfalse, isBot ) );
		if ( denied ) {
			// this generally shouldn't happen, because the client
			// was connected before the level change
			SV_DropClient( client, denied );
			Com_Printf( "SV_MapRestart_f(%d): dropped client %i - denied!\n", delay, i );
			continue;
		}

		if(client->state == CS_ACTIVE)
			SV_ClientEnterWorld(client, &client->lastUsercmd);
		else
		{
			// If we don't reset client->lastUsercmd and are restarting during map load,
			// the client will hang because we'll use the last Usercmd from the previous map,
			// which is wrong obviously.
			SV_ClientEnterWorld(client, NULL);
		}
	}	

	// run another frame to allow things to look at all the players
	VM_Call (gvm, GAME_RUN_FRAME, sv.time);
	sv.time += 100;
	svs.time += 100;
}
示例#16
0
文件: cvar.cpp 项目: vvvjk2/jk2mv
/*
============
Cvar_List_f
============
*/
void Cvar_List_f( void ) {
	cvar_t	*var;
	int		i;
	char	*match;

	if ( Cmd_Argc() > 1 ) {
		match = Cmd_Argv( 1 );
	} else {
		match = NULL;
	}

	i = 0;
	for (var = cvar_vars ; var ; var = var->next, i++)
	{
		// Dont show internal cvars
		if ( var->flags & CVAR_INTERNAL )
		{
			continue;
		}

		if (match && !Com_Filter(match, var->name, qfalse)) continue;

		if (var->flags & CVAR_SERVERINFO) {
			Com_Printf("S");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_USERINFO) {
			Com_Printf("U");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_ROM) {
			Com_Printf("R");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_INIT) {
			Com_Printf("I");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_ARCHIVE) {
			Com_Printf("A");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_LATCH) {
			Com_Printf("L");
		} else {
			Com_Printf(" ");
		}
		if (var->flags & CVAR_CHEAT) {
			Com_Printf("C");
		} else {
			Com_Printf(" ");
		}

		Com_Printf (" %s \"%s\"\n", var->name, var->string);
	}

	Com_Printf ("\n%i total cvars\n", i);
	Com_Printf ("%i cvar indexes\n", cvar_numIndexes);
}
static void SV_AddBanToList(qboolean isexception)
{
	char *banstring;
	char addy2[NET_ADDRSTRMAXLEN];
	netadr_t ip;
	int index, argc, mask;
	serverBan_t *curban;
	
	argc = Cmd_Argc();
	
	if(argc < 2 || argc > 3)
	{
		Com_Printf ("Usage: %s (ip[/subnet] | clientnum [subnet])\n", Cmd_Argv(0));
		return;
	}

	if(serverBansCount > ARRAY_LEN(serverBans))
	{
		Com_Printf ("Error: Maximum number of bans/exceptions exceeded.\n");
		return;
	}

	banstring = Cmd_Argv(1);
	
	if(strchr(banstring, '.') || strchr(banstring, ':'))
	{
		// This is an ip address, not a client num.
		
		if(SV_ParseCIDRNotation(&ip, &mask, banstring))
		{
			Com_Printf("Error: Invalid address %s\n", banstring);
			return;
		}
	}
	else
	{
		client_t *cl;
		
		// client num.
		if(!com_sv_running->integer)
		{
			Com_Printf("Server is not running.\n");
			return;
		}
		
		cl = SV_GetPlayerByNum();

		if(!cl)
		{
			Com_Printf("Error: Playernum %s does not exist.\n", Cmd_Argv(1));
			return;
		}
		
		ip = cl->netchan.remoteAddress;
		
		if(argc == 3)
		{
			mask = atoi(Cmd_Argv(2));
			
			if(ip.type == NA_IP)
			{
				if(mask < 1 || mask > 32)
					mask = 32;
			}
			else
			{
				if(mask < 1 || mask > 128)
					mask = 128;
			}
		}
		else
			mask = (ip.type == NA_IP6) ? 128 : 32;
	}

	if(ip.type != NA_IP && ip.type != NA_IP6)
	{
		Com_Printf("Error: Can ban players connected via the internet only.\n");
		return;
	}

	// first check whether a conflicting ban exists that would supersede the new one.
	for(index = 0; index < serverBansCount; index++)
	{
		curban = &serverBans[index];
		
		if(curban->subnet <= mask)
		{
			if((curban->isexception || !isexception) && NET_CompareBaseAdrMask(curban->ip, ip, curban->subnet))
			{
				Q_strncpyz(addy2, NET_AdrToString(ip), sizeof(addy2));
				
				Com_Printf("Error: %s %s/%d supersedes %s %s/%d\n", curban->isexception ? "Exception" : "Ban",
					   NET_AdrToString(curban->ip), curban->subnet,
					   isexception ? "exception" : "ban", addy2, mask);
				return;
			}
		}
		if(curban->subnet >= mask)
		{
			if(!curban->isexception && isexception && NET_CompareBaseAdrMask(curban->ip, ip, mask))
			{
				Q_strncpyz(addy2, NET_AdrToString(curban->ip), sizeof(addy2));
			
				Com_Printf("Error: %s %s/%d supersedes already existing %s %s/%d\n", isexception ? "Exception" : "Ban",
					   NET_AdrToString(ip), mask,
					   curban->isexception ? "exception" : "ban", addy2, curban->subnet);
				return;
			}
		}
	}

	// now delete bans that are superseded by the new one
	index = 0;
	while(index < serverBansCount)
	{
		curban = &serverBans[index];
		
		if(curban->subnet > mask && (!curban->isexception || isexception) && NET_CompareBaseAdrMask(curban->ip, ip, mask))
			SV_DelBanEntryFromList(index);
		else
			index++;
	}

	serverBans[serverBansCount].ip = ip;
	serverBans[serverBansCount].subnet = mask;
	serverBans[serverBansCount].isexception = isexception;
	
	serverBansCount++;
	
	SV_WriteBans();

	Com_Printf("Added %s: %s/%d\n", isexception ? "ban exception" : "ban",
		   NET_AdrToString(ip), mask);
}
示例#18
0
/*
* SVC_InfoResponse
* 
* Responds with short info for broadcast scans
* The second parameter should be the current protocol version number.
*/
static void SVC_InfoResponse( const socket_t *socket, const netadr_t *address )
{
	int i, count;
	char *string;
	qboolean allow_empty = qfalse, allow_full = qfalse;

	if( sv_showInfoQueries->integer )
		Com_Printf( "Info Packet %s\n", NET_AddressToString( address ) );

	// KoFFiE: When not public and coming from a LAN address
	//         assume broadcast and respond anyway, otherwise ignore
	if( ( ( !sv_public->integer ) && ( !NET_IsLANAddress( address ) ) ) ||
		( sv_maxclients->integer == 1 ) )
	{
		return;
	}

	// ignore when in invalid server state
	if( sv.state < ss_loading || sv.state > ss_game )
		return;

	// don't reply when we are locked for mm
	// if( SV_MM_IsLocked() )
	//	return;

	// different protocol version
	if( atoi( Cmd_Argv( 1 ) ) != APP_PROTOCOL_VERSION )
		return;

	// check for full/empty filtered states
	for( i = 0; i < Cmd_Argc(); i++ )
	{
		if( !Q_stricmp( Cmd_Argv( i ), "full" ) )
			allow_full = qtrue;

		if( !Q_stricmp( Cmd_Argv( i ), "empty" ) )
			allow_empty = qtrue;
	}

	count = 0;
	for( i = 0; i < sv_maxclients->integer; i++ )
	{
		if( svs.clients[i].state >= CS_CONNECTED )
		{
			count++;
		}
	}

	if( ( count == sv_maxclients->integer ) && !allow_full )
	{
		return;
	}

	if( ( count == 0 ) && !allow_empty )
	{
		return;
	}

	string = SV_ShortInfoString();
	if( string )
		Netchan_OutOfBandPrint( socket, address, "info\n%s", string );
}
示例#19
0
文件: cd_linux.c 项目: Izhido/qrevpak
static void CD_f (void)
{
	char	*command;
	int		ret;
	int		n;

	if (Cmd_Argc() < 2)
		return;

	command = Cmd_Argv (1);

	if (Q_strcasecmp(command, "on") == 0)
	{
		enabled = true;
		return;
	}

	if (Q_strcasecmp(command, "off") == 0)
	{
		if (playing)
			CDAudio_Stop();
		enabled = false;
		return;
	}

	if (Q_strcasecmp(command, "reset") == 0)
	{
		enabled = true;
		if (playing)
			CDAudio_Stop();
		for (n = 0; n < 100; n++)
			remap[n] = n;
		CDAudio_GetAudioDiskInfo();
		return;
	}

	if (Q_strcasecmp(command, "remap") == 0)
	{
		ret = Cmd_Argc() - 2;
		if (ret <= 0)
		{
			for (n = 1; n < 100; n++)
				if (remap[n] != n)
					Com_Printf("  %u -> %u\n", n, remap[n]);
			return;
		}
		for (n = 1; n <= ret; n++)
			remap[n] = atoi(Cmd_Argv (n+1));
		return;
	}

	if (Q_strcasecmp(command, "close") == 0)
	{
		CDAudio_CloseDoor();
		return;
	}

	if (!cdValid)
	{
		CDAudio_GetAudioDiskInfo();
		if (!cdValid)
		{
			Com_Printf("No CD in player.\n");
			return;
		}
	}

	if (Q_strcasecmp(command, "play") == 0)
	{
		CDAudio_Play((byte)atoi(Cmd_Argv (2)), false);
		return;
	}

	if (Q_strcasecmp(command, "loop") == 0)
	{
		CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
		return;
	}

	if (Q_strcasecmp(command, "stop") == 0)
	{
		CDAudio_Stop();
		return;
	}

	if (Q_strcasecmp(command, "pause") == 0)
	{
		CDAudio_Pause();
		return;
	}

	if (Q_strcasecmp(command, "resume") == 0)
	{
		CDAudio_Resume();
		return;
	}

	if (Q_strcasecmp(command, "eject") == 0)
	{
		if (playing)
			CDAudio_Stop();
		CDAudio_Eject();
		cdValid = false;
		return;
	}

	if (Q_strcasecmp(command, "info") == 0)
	{
		Com_Printf("%u tracks\n", maxTrack);
		if (playing)
			Com_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
		else if (wasPlaying)
			Com_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
		Com_Printf("Volume is %f\n", cdvolume);
		return;
	}
}
示例#20
0
/*
* SVC_DirectConnect
* A connection request that did not come from the master
*/
static void SVC_DirectConnect( const socket_t *socket, const netadr_t *address )
{
#ifdef TCP_ALLOW_CONNECT
	int incoming = 0;
#endif
	char userinfo[MAX_INFO_STRING];
	client_t *cl, *newcl;
	int i, version, game_port, challenge;
	int previousclients;
	int session_id;
	char *session_id_str;
	unsigned int ticket_id;
	qboolean tv_client;

	Com_DPrintf( "SVC_DirectConnect (%s)\n", Cmd_Args() );

	version = atoi( Cmd_Argv( 1 ) );
	if( version != APP_PROTOCOL_VERSION )
	{
		if( version <= 6 )
		{            // before reject packet was added
			Netchan_OutOfBandPrint( socket, address, "print\nServer is version %4.2f. Protocol %3i\n",
				APP_VERSION, APP_PROTOCOL_VERSION );
		}
		else
		{
			Netchan_OutOfBandPrint( socket, address,
				"reject\n%i\n%i\nServer and client don't have the same version\n", DROP_TYPE_GENERAL, 0 );
		}
		Com_DPrintf( "    rejected connect from protocol %i\n", version );
		return;
	}

	game_port = atoi( Cmd_Argv( 2 ) );
	challenge = atoi( Cmd_Argv( 3 ) );
	tv_client = ( atoi( Cmd_Argv( 5 ) ) & 1 ? qtrue : qfalse );

	if( !Info_Validate( Cmd_Argv( 4 ) ) )
	{
		Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nInvalid userinfo string\n", DROP_TYPE_GENERAL, 0 );
		Com_DPrintf( "Connection from %s refused: invalid userinfo string\n", NET_AddressToString( address ) );
		return;
	}

	Q_strncpyz( userinfo, Cmd_Argv( 4 ), sizeof( userinfo ) );

	// force the IP key/value pair so the game can filter based on ip
	if( !Info_SetValueForKey( userinfo, "socket", NET_SocketTypeToString( socket->type ) ) )
	{
		Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nError: Couldn't set userinfo (socket)\n",
			DROP_TYPE_GENERAL, 0 );
		Com_DPrintf( "Connection from %s refused: couldn't set userinfo (socket)\n", NET_AddressToString( address ) );
		return;
	}
	if( !Info_SetValueForKey( userinfo, "ip", NET_AddressToString( address ) ) )
	{
		Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nError: Couldn't set userinfo (ip)\n",
			DROP_TYPE_GENERAL, 0 );
		Com_DPrintf( "Connection from %s refused: couldn't set userinfo (ip)\n", NET_AddressToString( address ) );
		return;
	}

	if( Cmd_Argc() >= 7 )
	{
		// we have extended information, ticket-id and session-id
		Com_Printf("Extended information %s\n", Cmd_Argv(6) );
		ticket_id = (unsigned int)atoi( Cmd_Argv(6) );
		session_id_str = Info_ValueForKey( userinfo, "cl_mm_session" );
		if( session_id_str != NULL )
			session_id = atoi( session_id_str );
		else
			session_id = 0;
	}
	else
	{
		ticket_id = 0;
		session_id = 0;
	}

#ifdef TCP_ALLOW_CONNECT
	if( socket->type == SOCKET_TCP )
	{
		// find the connection
		for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ )
		{
			if( !svs.incoming[i].active )
				continue;

			if( NET_CompareAddress( &svs.incoming[i].address, address ) && socket == &svs.incoming[i].socket )
				break;
		}
		if( i == MAX_INCOMING_CONNECTIONS )
		{
			Com_Error( ERR_FATAL, "Incoming connection not found.\n" );
			return;
		}
		incoming = i;
	}
#endif

	// see if the challenge is valid
	for( i = 0; i < MAX_CHALLENGES; i++ )
	{
		if( NET_CompareBaseAddress( address, &svs.challenges[i].adr ) )
		{
			if( challenge == svs.challenges[i].challenge )
			{
				svs.challenges[i].challenge = 0; // wsw : r1q2 : reset challenge
				svs.challenges[i].time = 0;
				NET_InitAddress( &svs.challenges[i].adr, NA_NOTRANSMIT );
				break; // good
			}
			Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nBad challenge\n",
				DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT );
			return;
		}
	}
	if( i == MAX_CHALLENGES )
	{
		Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nNo challenge for address\n",
			DROP_TYPE_GENERAL, DROP_FLAG_AUTORECONNECT );
		return;
	}

	//r1: limit connections from a single IP
	if( sv_iplimit->integer )
	{
		previousclients = 0;
		for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
		{
			if( cl->state == CS_FREE )
				continue;
			if( NET_CompareBaseAddress( address, &cl->netchan.remoteAddress ) )
			{
				//r1: zombies are less dangerous
				if( cl->state == CS_ZOMBIE )
					previousclients++;
				else
					previousclients += 2;
			}
		}

		if( previousclients >= sv_iplimit->integer * 2 )
		{
			Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nToo many connections from your host\n", DROP_TYPE_GENERAL,
				DROP_FLAG_AUTORECONNECT );
			Com_DPrintf( "%s:connect rejected : too many connections\n", NET_AddressToString( address ) );
			return;
		}
	}

	newcl = NULL;

	// if there is already a slot for this ip, reuse it
	for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
	{
		if( cl->state == CS_FREE )
			continue;
		if( NET_CompareAddress( address, &cl->netchan.remoteAddress ) ||
			( NET_CompareBaseAddress( address, &cl->netchan.remoteAddress ) && cl->netchan.game_port == game_port ) )
		{
			if( !NET_IsLocalAddress( address ) &&
				( svs.realtime - cl->lastconnect ) < (unsigned)( sv_reconnectlimit->integer * 1000 ) )
			{
				Com_DPrintf( "%s:reconnect rejected : too soon\n", NET_AddressToString( address ) );
				return;
			}
			Com_Printf( "%s:reconnect\n", NET_AddressToString( address ) );
			newcl = cl;
			break;
		}
	}

	// find a client slot
	if( !newcl )
	{
		for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
		{
			if( cl->state == CS_FREE )
			{
				newcl = cl;
				break;
			}
			// overwrite fakeclient if no free spots found
			if( cl->state && cl->edict && ( cl->edict->r.svflags & SVF_FAKECLIENT ) )
				newcl = cl;
		}
		if( !newcl )
		{
			Netchan_OutOfBandPrint( socket, address, "reject\n%i\n%i\nServer is full\n", DROP_TYPE_GENERAL,
				DROP_FLAG_AUTORECONNECT );
			Com_DPrintf( "Server is full. Rejected a connection.\n" );
			return;
		}
		if( newcl->state && newcl->edict && ( newcl->edict->r.svflags & SVF_FAKECLIENT ) )
			SV_DropClient( newcl, DROP_TYPE_GENERAL, "Need room for a real player" );
	}

	// get the game a chance to reject this connection or modify the userinfo
	if( !SV_ClientConnect( socket, address, newcl, userinfo, game_port, challenge, qfalse, tv_client, ticket_id, session_id ) )
	{
		char *rejtype, *rejflag, *rejtypeflag, *rejmsg;

		rejtype = Info_ValueForKey( userinfo, "rejtype" );
		if( !rejtype )
			rejtype = "0";
		rejflag = Info_ValueForKey( userinfo, "rejflag" );
		if( !rejflag )
			rejflag = "0";
		// hax because Info_ValueForKey can only be called twice in a row
		rejtypeflag = va( "%s\n%s", rejtype, rejflag );

		rejmsg = Info_ValueForKey( userinfo, "rejmsg" );
		if( !rejmsg )
			rejmsg = "Game module rejected connection";

		Netchan_OutOfBandPrint( socket, address, "reject\n%s\n%s\n", rejtypeflag, rejmsg );

		Com_DPrintf( "Game rejected a connection.\n" );
		return;
	}

	// send the connect packet to the client
	Netchan_OutOfBandPrint( socket, address, "client_connect" );

	// free the incoming entry
#ifdef TCP_ALLOW_CONNECT
	if( socket->type == SOCKET_TCP )
	{
		svs.incoming[incoming].active = qfalse;
		svs.incoming[incoming].socket.open = qfalse;
	}
#endif
}
示例#21
0
/*
==================
SV_Map_f

Restart the server on a different map
==================
*/
static void SV_Map_f(void)
{
	char     *cmd;
	char     *map;
	char     smapname[MAX_QPATH];
	char     mapname[MAX_QPATH];
	qboolean killBots, cheat, buildScript;
	char     expanded[MAX_QPATH];
	int      savegameTime   = -1;
	char     *cl_profileStr = Cvar_VariableString("cl_profile");

	map = Cmd_Argv(1);
	if (!map)
	{
		return;
	}

	if (!com_gameInfo.spEnabled)
	{
		if (!Q_stricmp(Cmd_Argv(0), "spdevmap") || !Q_stricmp(Cmd_Argv(0), "spmap"))
		{
			Com_Printf("Single Player is not enabled.\n");
			return;
		}
	}

	buildScript = Cvar_VariableIntegerValue("com_buildScript");

	if (SV_GameIsSinglePlayer())
	{
		if (!buildScript && sv_reloading->integer && sv_reloading->integer != RELOAD_NEXTMAP)     // game is in 'reload' mode, don't allow starting new maps yet.
		{
			return;
		}

		// Trap a savegame load
		if (strstr(map, ".sav"))
		{
			// open the savegame, read the mapname, and copy it to the map string
			char savemap[MAX_QPATH];
			char savedir[MAX_QPATH];
			byte *buffer;
			int  size, csize;

			if (com_gameInfo.usesProfiles && cl_profileStr[0])
			{
				Com_sprintf(savedir, sizeof(savedir), "profiles/%s/save/", cl_profileStr);
			}
			else
			{
				Q_strncpyz(savedir, "save/", sizeof(savedir));
			}

			if (!(strstr(map, savedir) == map))
			{
				Com_sprintf(savemap, sizeof(savemap), "%s%s", savedir, map);
			}
			else
			{
				strcpy(savemap, map);
			}

			size = FS_ReadFile(savemap, NULL);
			if (size < 0)
			{
				Com_Printf("Can't find savegame %s\n", savemap);
				return;
			}

			//buffer = Hunk_AllocateTempMemory(size);
			FS_ReadFile(savemap, (void **)&buffer);

			if (Q_stricmp(savemap, va("%scurrent.sav", savedir)) != 0)
			{
				// copy it to the current savegame file
				FS_WriteFile(va("%scurrent.sav", savedir), buffer, size);
				// make sure it is the correct size
				csize = FS_ReadFile(va("%scurrent.sav", savedir), NULL);
				if (csize != size)
				{
					Hunk_FreeTempMemory(buffer);
					FS_Delete(va("%scurrent.sav", savedir));
// TTimo
#ifdef __linux__
					Com_Error(ERR_DROP, "Unable to save game.\n\nPlease check that you have at least 5mb free of disk space in your home directory.");
#else
					Com_Error(ERR_DROP, "Insufficient free disk space.\n\nPlease free at least 5mb of free space on game drive.");
#endif
					return;
				}
			}

			// set the cvar, so the game knows it needs to load the savegame once the clients have connected
			Cvar_Set("savegame_loading", "1");
			// set the filename
			Cvar_Set("savegame_filename", savemap);

			// the mapname is at the very start of the savegame file
			Com_sprintf(savemap, sizeof(savemap), ( char * )(buffer + sizeof(int)));          // skip the version
			Q_strncpyz(smapname, savemap, sizeof(smapname));
			map = smapname;

			savegameTime = *( int * )(buffer + sizeof(int) + MAX_QPATH);

			if (savegameTime >= 0)
			{
				svs.time = savegameTime;
			}

			Hunk_FreeTempMemory(buffer);
		}
		else
		{
			Cvar_Set("savegame_loading", "0");    // make sure it's turned off
			// set the filename
			Cvar_Set("savegame_filename", "");
		}
	}
	else
	{
		Cvar_Set("savegame_loading", "0");    // make sure it's turned off
		// set the filename
		Cvar_Set("savegame_filename", "");
	}

	// make sure the level exists before trying to change, so that
	// a typo at the server console won't end the game
	Com_sprintf(expanded, sizeof(expanded), "maps/%s.bsp", map);
	if (FS_ReadFile(expanded, NULL) == -1)
	{
		Com_Printf("Can't find map %s\n", expanded);
		return;
	}

	Cvar_Set("gamestate", va("%i", GS_INITIALIZE));           // NERVE - SMF - reset gamestate on map/devmap

	Cvar_Set("g_currentRound", "0");              // NERVE - SMF - reset the current round
	Cvar_Set("g_nextTimeLimit", "0");             // NERVE - SMF - reset the next time limit

	// START	Mad Doctor I changes, 8/14/2002.  Need a way to force load a single player map as single player
	if (!Q_stricmp(Cmd_Argv(0), "spdevmap") || !Q_stricmp(Cmd_Argv(0), "spmap"))
	{
		// This is explicitly asking for a single player load of this map
		Cvar_Set("g_gametype", va("%i", com_gameInfo.defaultSPGameType));
		// force latched values to get set
		Cvar_Get("g_gametype", va("%i", com_gameInfo.defaultSPGameType), CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH);
		// enable bot support for AI
		Cvar_Set("bot_enable", "1");
	}

	// Rafael gameskill
//	Cvar_Get ("g_gameskill", "3", CVAR_SERVERINFO | CVAR_LATCH);
	// done

	cmd = Cmd_Argv(0);

	if (!Q_stricmp(cmd, "devmap"))
	{
		cheat    = qtrue;
		killBots = qtrue;
	}
	else
	if (!Q_stricmp(Cmd_Argv(0), "spdevmap"))
	{
		cheat    = qtrue;
		killBots = qtrue;
	}
	else
	{
		cheat    = qfalse;
		killBots = qfalse;
	}

	// save the map name here cause on a map restart we reload the q3config.cfg
	// and thus nuke the arguments of the map command
	Q_strncpyz(mapname, map, sizeof(mapname));

	// start up the map
	SV_SpawnServer(mapname, killBots);

	// set the cheat value
	// if the level was started with "map <levelname>", then
	// cheats will not be allowed.  If started with "devmap <levelname>"
	// then cheats will be allowed
	if (cheat)
	{
		Cvar_Set("sv_cheats", "1");
	}
	else
	{
		Cvar_Set("sv_cheats", "0");
	}
}
示例#22
0
// Checks if we have a keycode at the end, e.g. +fire 8 5 3 120
// if it's >= 32, treat is as keycodes, otherwise an impulse
static qbool IN_IsLastArgKeyCode(void)
{
	return atoi(Cmd_Argv(Cmd_Argc() - 1)) >= 32;
}
示例#23
0
/*
=================
SV_LoadGame_f
=================
*/
void    SV_LoadGame_f(void)
{
	char filename[MAX_QPATH], mapname[MAX_QPATH], savedir[MAX_QPATH];
	byte *buffer;
	int  size;
	char *cl_profileStr = Cvar_VariableString("cl_profile");

	// dont allow command if another loadgame is pending
	if (Cvar_VariableIntegerValue("savegame_loading"))
	{
		return;
	}
	if (sv_reloading->integer)
	{
		// (SA) disabling
//	if(sv_reloading->integer && sv_reloading->integer != RELOAD_FAILED )	// game is in 'reload' mode, don't allow starting new maps yet.
		return;
	}

	Q_strncpyz(filename, Cmd_Argv(1), sizeof(filename));
	if (!filename[0])
	{
		Com_Printf("You must specify a savegame to load\n");
		return;
	}

	if (com_gameInfo.usesProfiles && cl_profileStr[0])
	{
		Com_sprintf(savedir, sizeof(savedir), "profiles/%s/save/", cl_profileStr);
	}
	else
	{
		Q_strncpyz(savedir, "save/", sizeof(savedir));
	}

	/*if ( Q_strncmp( filename, "save/", 5 ) && Q_strncmp( filename, "save\\", 5 ) ) {
	    Q_strncpyz( filename, va("save/%s", filename), sizeof( filename ) );
	}*/

	// go through a va to avoid vsnprintf call with same source and target
	Q_strncpyz(filename, va("%s%s", savedir, filename), sizeof(filename));

	// enforce .sav extension
	if (!strstr(filename, ".") || Q_strncmp(strstr(filename, ".") + 1, "sav", 3))
	{
		Q_strcat(filename, sizeof(filename), ".sav");
	}
	// use '/' instead of '\\' for directories
	while (strstr(filename, "\\"))
	{
		*(char *)strstr(filename, "\\") = '/';
	}

	size = FS_ReadFile(filename, NULL);
	if (size < 0)
	{
		Com_Printf("Can't find savegame %s\n", filename);
		return;
	}

	//buffer = Hunk_AllocateTempMemory(size);
	FS_ReadFile(filename, (void **)&buffer);

	// read the mapname, if it is the same as the current map, then do a fast load
	Com_sprintf(mapname, sizeof(mapname), (const char *)(buffer + sizeof(int)));

	if (com_sv_running->integer && (com_frameTime != sv.serverId))
	{
		// check mapname
		if (!Q_stricmp(mapname, sv_mapname->string))          // same
		{
			if (Q_stricmp(filename, va("%scurrent.sav", savedir)) != 0)
			{
				// copy it to the current savegame file
				FS_WriteFile(va("%scurrent.sav", savedir), buffer, size);
			}

			Hunk_FreeTempMemory(buffer);

			Cvar_Set("savegame_loading", "2");    // 2 means it's a restart, so stop rendering until we are loaded
			// set the filename
			Cvar_Set("savegame_filename", filename);
			// quick-restart the server
			SV_MapRestart_f();  // savegame will be loaded after restart

			return;
		}
	}

	Hunk_FreeTempMemory(buffer);

	// otherwise, do a slow load
	if (Cvar_VariableIntegerValue("sv_cheats"))
	{
		Cbuf_ExecuteText(EXEC_APPEND, va("spdevmap %s", filename));
	}
	else        // no cheats
	{
		Cbuf_ExecuteText(EXEC_APPEND, va("spmap %s", filename));
	}
}
示例#24
0
// This is the same command as impulse but cl_weaponpreselect can be used in here, while for impulses cannot be used.
void IN_Weapon(void)
{
	int c, best, mode;
	if ((c = Cmd_Argc() - 1) < 1) {
		Com_Printf("Usage: %s w1 [w2 [w3..]]\nWill pre-select best available weapon from given sequence.\n", Cmd_Argv(0));
		return;
	}

	// read user input
	IN_RememberWpOrder();

	best = IN_BestWeapon();

	mode = (int) cl_weaponpreselect.value;

	// cl_weaponpreselect behaviour:
	// 0: select best weapon right now
	// 1: always only pre-select; switch to it on +attack
	// 2: user is holding +attack -> select, otherwise just pre-select
	// 3: same like 1, but only in deathmatch 1
	// 4: same like 2, but only in deathmatch 1
	if (mode == 3) {
		mode = (cl.deathmatch == 1) ? 1 : 0;
	}
	else if (mode == 4) {
		mode = (cl.deathmatch == 1) ? 2 : 0;
	}

	switch (mode)
	{
		case 2:
			if ((in_attack.state & 3) && best) // user is holding +attack and there is some weapon available
				in_impulse = best;
			break;
		case 1: break;	// don't select weapon immediately
		default: case 0:	// no pre-selection
			if (best)
				in_impulse = best;

			break;
	}
}
示例#25
0
void Master_SetMaster_f() {

   int AreAdding;
   const char * arg_1, * arg_2;
   int port;
   netadr_t netaddress;
   master_server_t * ptr, * ptr2;

   if(Cmd_Argc() < 2 || Cmd_Argc() > 4) {

      Con_Printf("Setmaster <add | remove | enable | disable> <IP:port>\n");
      Con_Printf(" Current master list:\n");

      for(ptr = masterlist; ptr != NULL; ptr = ptr->next) {

         Con_Printf("  %s\n", NET_AdrToString(ptr->address));
      }

      Con_Printf(" End if list\n");
      return;
   }

   arg_1 = Cmd_Argv(1);
   if(arg_1[0] == '\0') { return; }

   if(Q_strcasecmp(arg_1, "disable") == 0) { gfNoMasterServer = 1; return; }
   if(Q_strcasecmp(arg_1, "enable") == 0) { gfNoMasterServer = 0; return; }

   if(Q_strcasecmp(arg_1, "add") == 0) { AreAdding = 1; }
   else if(Q_strcasecmp(arg_1, "remove") == 0) { AreAdding = 0; }
   else {

      Con_Printf("Setmaster:  Unknown command \"%s\".\n", arg_1);
      return;
   }

   arg_2 = Cmd_Argv(2);

   if(Cmd_Argc() == 4) {
      port = Q_atoi(Cmd_Argv(3));
      if(port < 1 || port > 65535) {
         Con_Printf("Setmaster: Invalid port.  Ports can't be larger than 65535.\n");
         return;
      }
   }
   else {
      port = 27010;
   }

   if(NET_StringToAdr(arg_2, &netaddress) == 0) {
      Con_Printf("Setmaster: Passed address could not be processed by StringToAdr.\n");
      return;
   }
   netaddress.port = port;

   if(AreAdding) {

      Master_Init();
      Master_AddServer(&netaddress);
      gfNoMasterServer = 0;
      Con_Printf("Master server %s:%u added.\n", arg_2, port);
   }
   else {

      //case 1: first node.
      if(NET_CompareAdr(masterlist->address, netaddress) != 0) {
         ptr = masterlist;
         masterlist = masterlist->next;
         Q_Free(ptr);
         return;
      }

      //case 2: some node afterwards
      for(ptr = masterlist; ptr->next != NULL; ptr = ptr->next) {
         if(NET_CompareAdr(ptr->next->address, netaddress) != 0) {

            ptr2 = ptr->next;
            ptr->next = ptr->next->next;
            Q_Free(ptr2);
            return;
         }
      }
      //case 3: not here
      Con_Printf("Master %s:%u couldn't be removed.  Couldn't find it.\n", arg_2, port);
   }
}
/*
==================
SV_PP_Cmd_Argc_to_idnum

@Barbatos: wow this one looks horrible, FIXME!
==================
*/
int SV_Argc_to_idnum( int arg_num ) {
	client_t	*cl;
	int			idnum;
	int			i, k, f, g;
	int			len, nlen, slen;
	int			count;
	char		*search;
	char		*name;

	// make sure server is running
	if ( !com_sv_running->integer ) {
		return -1;
	}

	if ( Cmd_Argc() < 1 ) {
		Com_Printf( "No player specified.\n" );
		return -1;
	}

	search = Cmd_Argv( arg_num );

	if(strlen( search ) < 3 )
	{
		for (i = 0; search[i]; i++) {
			if (search[i] < '0' || search[i] > '9') {
				Com_Printf( "Bad slot number: \"%s\".\n", search);
				return -1;
			}
		}
		idnum = atoi( search );
		if ( idnum < 0 || idnum >= sv_maxclients->integer ) {
			Com_Printf( "Bad client slot: %i.\n", idnum );
			return -1;
		}

		cl = &svs.clients[idnum];
		if ( !cl->state ) {
			Com_Printf( "Client %i is not active.\n", idnum );
			return -1;
		}
		return idnum;
	}
	else
	{
		f = 0; g = 0;
		count = 0;
		idnum = -1;
		slen = strlen(search);
		for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) {
			if ( cl->state >= CS_CONNECTED ) {
				name = cl->name;
				nlen = strlen(name);
				len = nlen - slen;
				if(len>=0) {
					for (k=0; k<=len; k++, name++) {
						if( toupper(name[0])==toupper(search[0]) ) {
							for (g=1,f=1; search[f] && name[g]; g++) {
								if( Q_IsColorString( &name[g] ) ) {
									g++;
								} else {
									if( toupper(name[g])!=toupper(search[f]) ) break;
									f++;
								}
							}
							if (f==slen) { 
								count++; 
								idnum = i; 
								break; 
							}
						}
					}
				}
			}
		}
		if( count == 1 ) { 
			return idnum;
		}
		if( count > 0 ) { 
			Com_Printf( "Too many players found for \"%s\".\n", search );
			return -1;
		}
		if( count == 0 ) { 
			Com_Printf( "No player found for \"%s\".\n", search );
			return -1;
		}
	}

	return -1;
}
示例#27
0
文件: r_misc.c 项目: chrisglass/ufoai
/**
 * Take a screenshot of the frame buffer
 * @param[in] x
 * @param[in] y
 * @param[in] width
 * @param[in] height
 * @param[in] filename Force to use a filename. Else NULL to autogen a filename
 * @param[in] ext Force to use an image format (tga/png/jpg). Else NULL to use value of r_screenshot_format
 */
void R_ScreenShot (int x, int y, int width, int height, const char *filename, const char *ext)
{
	char	checkName[MAX_OSPATH];
	int		type, shotNum, quality = 100;
	byte	*buffer;
	qFILE	f;
	int rowPack;

	glGetIntegerv(GL_PACK_ALIGNMENT, &rowPack);
	glPixelStorei(GL_PACK_ALIGNMENT, 1);

	/* Find out what format to save in */
	if (ext == NULL)
		ext = r_screenshot_format->string;

	if (!Q_strcasecmp(ext, "png"))
		type = SSHOTTYPE_PNG;
	else if (!Q_strcasecmp(ext, "jpg"))
		type = SSHOTTYPE_JPG;
	else
		type = SSHOTTYPE_TGA_COMP;

	/* Set necessary values */
	switch (type) {
	case SSHOTTYPE_TGA_COMP:
		Com_Printf("Taking TGA screenshot...\n");
		ext = "tga";
		break;

	case SSHOTTYPE_PNG:
		Com_Printf("Taking PNG screenshot...\n");
		ext = "png";
		break;

	case SSHOTTYPE_JPG:
		if (Cmd_Argc() == 3)
			quality = atoi(Cmd_Argv(2));
		else
			quality = r_screenshot_jpeg_quality->integer;
		if (quality > 100 || quality <= 0)
			quality = 100;

		Com_Printf("Taking JPG screenshot (at %i%% quality)...\n", quality);
		ext = "jpg";
		break;
	}

	/* Find a file name to save it to */
	if (filename) {
		Com_sprintf(checkName, sizeof(checkName), "scrnshot/%s.%s", filename, ext);
	} else {
		for (shotNum = 0; shotNum < 1000; shotNum++) {
			Com_sprintf(checkName, sizeof(checkName), "scrnshot/ufo%i%i.%s", shotNum / 10, shotNum % 10, ext);
			if (FS_CheckFile("%s", checkName) == -1)
				break;
		}
		if (shotNum == 1000) {
			Com_Printf("R_ScreenShot_f: screenshot limit (of 1000) exceeded!\n");
			return;
		}
	}

	/* Open it */
	FS_OpenFile(checkName, &f, FILE_WRITE);
	if (!f.f) {
		Com_Printf("R_ScreenShot_f: Couldn't create file: %s\n", checkName);
		return;
	}

	/* Allocate room for a copy of the framebuffer */
	buffer = (byte *)Mem_PoolAlloc(width * height * 3, vid_imagePool, 0);
	if (!buffer) {
		Com_Printf("R_ScreenShot_f: Could not allocate %i bytes for screenshot!\n", width * height * 3);
		FS_CloseFile(&f);
		return;
	}

	/* Read the framebuffer into our storage */
	glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
	R_CheckError();

	/* Write */
	switch (type) {
	case SSHOTTYPE_TGA_COMP:
		R_WriteCompressedTGA(&f, buffer, width, height);
		break;

	case SSHOTTYPE_PNG:
		R_WritePNG(&f, buffer, width, height);
		break;

	case SSHOTTYPE_JPG:
		R_WriteJPG(&f, buffer, width, height, quality);
		break;
	}

	/* Finish */
	FS_CloseFile(&f);
	Mem_Free(buffer);

	Com_Printf("Wrote %s to %s\n", checkName, FS_Gamedir());
	glPixelStorei(GL_PACK_ALIGNMENT, rowPack);
}
/*
==================
SV_Map_f

Restart the server on a different map
==================
*/
static void SV_Map_f( void ) {
	char		*cmd;
	char		*map;
	qboolean	killBots, cheat;
	char		expanded[MAX_QPATH];
	char		mapname[MAX_QPATH];

	map = Cmd_Argv(1);
	if ( !map ) {
		return;
	}

	// make sure the level exists before trying to change, so that
	// a typo at the server console won't end the game
	Com_sprintf (expanded, sizeof(expanded), "maps/%s.bsp", map);
	if ( FS_ReadFile (expanded, NULL) == -1 ) {
		Com_Printf ("Can't find map %s\n", expanded);
		return;
	}

	// force latched values to get set
	Cvar_Get ("g_gametype", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH );

	cmd = Cmd_Argv(0);
	if( Q_stricmpn( cmd, "sp", 2 ) == 0 ) {
		Cvar_SetValue( "g_gametype", GT_SINGLE_PLAYER );
		Cvar_SetValue( "g_doWarmup", 0 );
		// may not set sv_maxclients directly, always set latched
		Cvar_SetLatched( "sv_maxclients", "8" );
		cmd += 2;
		if (!Q_stricmp( cmd, "devmap" ) ) {
			cheat = qtrue;
		} else {
			cheat = qfalse;
		}
		killBots = qtrue;
	}
	else {
		if ( !Q_stricmp( cmd, "devmap" ) ) {
			cheat = qtrue;
			killBots = qtrue;
		} else {
			cheat = qfalse;
			killBots = qfalse;
		}
		if( sv_gametype->integer == GT_SINGLE_PLAYER ) {
			Cvar_SetValue( "g_gametype", GT_FFA );
		}
	}

	// save the map name here cause on a map restart we reload the q3config.cfg
	// and thus nuke the arguments of the map command
	Q_strncpyz(mapname, map, sizeof(mapname));

	// start up the map
	SV_SpawnServer( mapname, killBots );

	// set the cheat value
	// if the level was started with "map <levelname>", then
	// cheats will not be allowed.  If started with "devmap <levelname>"
	// then cheats will be allowed
	if ( cheat ) {
		Cvar_Set( "sv_cheats", "1" );
	} else {
		Cvar_Set( "sv_cheats", "0" );
	}
}
示例#29
0
void TP_MsgTrigger_f (void)
{
	int c;
	char *name;
	msg_trigger_t *trig;
 
	c = Cmd_Argc();
 
	if (c > 5) {
		Com_Printf ("msg_trigger <trigger name> \"string\" [-l <level>]\n");
		return;
	}
 
	if (c == 1) {
		if (!msg_triggers)
			Com_Printf ("no triggers defined\n");
		else
			for (trig=msg_triggers; trig; trig=trig->next)
				Com_Printf ("%s : \"%s\"\n", trig->name, trig->string);
		return;
	}
 
	name = Cmd_Argv(1);
	if (strlen(name) > 31) {
		Com_Printf ("trigger name too long\n");
		return;
	}
 
	if (c == 2) {
		trig = TP_FindTrigger (name);
		if (trig)
			Com_Printf ("%s: \"%s\"\n", trig->name, trig->string);
		else
			Com_Printf ("trigger \"%s\" not found\n", name);
		return;
	}
 
	if (c >= 3) {
		if (strlen(Cmd_Argv(2)) > 63) {
			Com_Printf ("trigger string too long\n");
			return;
		}
 
		if (!(trig = TP_FindTrigger (name))) {
			// allocate new trigger
			trig = (msg_trigger_t *) Q_malloc(sizeof(msg_trigger_t));
			trig->next = msg_triggers;
			msg_triggers = trig;
			strlcpy (trig->name, name, sizeof (trig->name));
			trig->level = PRINT_HIGH;
		}
 
		strlcpy (trig->string, Cmd_Argv(2), sizeof(trig->string));
		if (c == 5 && !strcasecmp (Cmd_Argv(3), "-l")) {
			if (!strcmp(Cmd_Argv(4), "t")) {
				trig->level = 4;
			} else {
				trig->level = Q_atoi (Cmd_Argv(4));
				if ((unsigned) trig->level > PRINT_CHAT)
					trig->level = PRINT_HIGH;
			}
		}
	}
}
示例#30
0
/*
================
SVC_Info

Responds with a short info message that should be enough to determine
if a user is interested in a server to do a full status
================
*/
void SVC_Info( netadr_t from ) {
	int		i, count;
	char	*gamedir;
	char	infostring[MAX_INFO_STRING];

	// ignore if we are in single player
	if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
		return;
	}

	/*
	 * Check whether Cmd_Argv(1) has a sane length. This was not done in the original Quake3 version which led
	 * to the Infostring bug discovered by Luigi Auriemma. See http://aluigi.altervista.org/ for the advisory.
	 */

	// A maximum challenge length of 128 should be more than plenty.
	if(strlen(Cmd_Argv(1)) > 128)
		return;

	// don't count privateclients
	count = 0;
	for ( i = sv_privateClients->integer ; i < sv_maxclients->integer ; i++ ) {
		if ( svs.clients[i].state >= CS_CONNECTED ) {
			count++;
		}
	}

	infostring[0] = 0;

	// echo back the parameter to status. so servers can use it as a challenge
	// to prevent timed spoofed reply packets that add ghost servers
	Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );

	Info_SetValueForKey( infostring, "protocol", va("%i", PROTOCOL_VERSION) );
	Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
	Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
	Info_SetValueForKey( infostring, "clients", va("%i", count) );
	Info_SetValueForKey( infostring, "sv_maxclients", 
		va("%i", sv_maxclients->integer - sv_privateClients->integer ) );
	Info_SetValueForKey( infostring, "gametype", va("%i", sv_gametype->integer ) );
	Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) );

#ifdef USE_VOIP
	if (sv_voip->integer) {
		Info_SetValueForKey( infostring, "voip", va("%i", sv_voip->integer ) );
	}
#endif

	if( sv_minPing->integer ) {
		Info_SetValueForKey( infostring, "minPing", va("%i", sv_minPing->integer) );
	}
	if( sv_maxPing->integer ) {
		Info_SetValueForKey( infostring, "maxPing", va("%i", sv_maxPing->integer) );
	}
	gamedir = Cvar_VariableString( "fs_game" );
	if( *gamedir ) {
		Info_SetValueForKey( infostring, "game", gamedir );
	}

	NET_OutOfBandPrint( NS_SERVER, from, "infoResponse\n%s", infostring );
}