void SV_WriteDemoArchive(client_t *client){

	byte bufData[72];
	msg_t msg;

	MSG_Init(&msg, bufData, sizeof(bufData));

	int archiveIndex;
	playerState_t *ps = SV_GameClientNum(client - svs.clients);
	vec3_t nullvec = {0, 0, 0};

	MSG_WriteByte(&msg, 1);

	archiveIndex = client->demoArchiveIndex % 256;
	MSG_WriteLong(&msg, archiveIndex);
	MSG_WriteVector(&msg, ps->origin);

	MSG_WriteVector(&msg, nullvec);
	MSG_WriteLong(&msg, 0); //Velocity

	MSG_WriteLong(&msg, 0);
	MSG_WriteLong(&msg, ps->commandTime);
	MSG_WriteVector(&msg, ps->viewangles);
	client->demoArchiveIndex++;

	FS_DemoWrite( msg.data, msg.cursize, &client->demofile );
}
示例#2
0
/**
 * @brief Creates client information for other functions
 * @param clientNum Client ID (from 0 to MAX_CLIENTS)
 * @note Just for sv_trackbase.c internal use
 */
char *Tracker_createClientInfo(int clientNum)
{
	playerState_t *ps;
	ps = SV_GameClientNum(clientNum);

	return va("%i\\%i\\%c\\%i\\%s", svs.clients[clientNum].ping, ps->persistant[PERS_SCORE], Info_ValueForKey(Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE), "P")[clientNum], ps->stats[STAT_PLAYER_CLASS], svs.clients[clientNum].name);
}
示例#3
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void ) {
	int			i, j, l;
	client_t	*cl;
	playerState_t	*ps;
	const char		*s;
	int			ping;

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

	Com_Printf ("map: %s\n", sv_mapname->string );

	Com_Printf ("num score ping name            lastmsg address               qport rate\n");
	Com_Printf ("--- ----- ---- --------------- ------- --------------------- ----- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
			continue;
		Com_Printf ("%3i ", i);
		ps = SV_GameClientNum( i );
		Com_Printf ("%5i ", ps->persistant[PERS_SCORE]);

		if (cl->state == CS_CONNECTED)
			Com_Printf ("CNCT ");
		else if (cl->state == CS_ZOMBIE)
			Com_Printf ("ZMBI ");
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf ("%4i ", ping);
		}

		Com_Printf ("%s", cl->name);
    // TTimo adding a ^7 to reset the color
    // NOTE: colored names in status breaks the padding (WONTFIX)
    Com_Printf ("^7");
		l = 16 - strlen(cl->name);
		for (j=0 ; j<l ; j++)
			Com_Printf (" ");

		Com_Printf ("%7i ", svs.time - cl->lastPacketTime );

		s = NET_AdrToString( cl->netchan.remoteAddress );
		Com_Printf ("%s", s);
		l = 22 - strlen(s);
		for (j=0 ; j<l ; j++)
			Com_Printf (" ");
		
		Com_Printf ("%5i", cl->netchan.qport);

		Com_Printf (" %5i", cl->rate);

		Com_Printf ("\n");
	}
	Com_Printf ("\n");
}
示例#4
0
/*
===================
SV_CalcPings

Updates the cl->ping variables
===================
*/
void SV_CalcPings( void ) {
	int i, j;
	client_t    *cl;
	int total, count;
	int delta;
	playerState_t   *ps;

	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
		cl = &svs.clients[i];

#if defined RTCW_MP
		// DHM - Nerve
#ifdef UPDATE_SERVER
		if ( !cl ) {
			continue;
		}
#endif
#endif // RTCW_XX

		if ( cl->state != CS_ACTIVE ) {
			cl->ping = 999;
			continue;
		}
		if ( !cl->gentity ) {
			cl->ping = 999;
			continue;
		}
		if ( cl->gentity->r.svFlags & SVF_BOT ) {
			cl->ping = 0;
			continue;
		}

		total = 0;
		count = 0;
		for ( j = 0 ; j < PACKET_BACKUP ; j++ ) {
			if ( cl->frames[j].messageAcked <= 0 ) {
				continue;
			}
			delta = cl->frames[j].messageAcked - cl->frames[j].messageSent;
			count++;
			total += delta;
		}
		if ( !count ) {
			cl->ping = 999;
		} else {
			cl->ping = total / count;
			if ( cl->ping > 999 ) {
				cl->ping = 999;
			}
		}

		// let the game dll know about the ping
		ps = SV_GameClientNum( i );
		ps->ping = cl->ping;
	}
}
示例#5
0
/*
================
SVC_Status

Responds with all the info that qplug or qspy can see about the server
and all connected players.  Used for getting detailed information after
the simple info query.
================
*/
void SVC_Status( netadr_t from ) {
	char player[1024];
	char status[MAX_MSGLEN];
	int i;
	client_t    *cl;
	playerState_t   *ps;
	int statusLength;
	int playerLength;
	char infostring[MAX_INFO_STRING];

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

	// DHM - Nerve
#ifdef UPDATE_SERVER
	return;
#endif

	strcpy( infostring, Cvar_InfoString( CVAR_SERVERINFO ) );

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

	// add "demo" to the sv_keywords if restricted
	if ( Cvar_VariableValue( "fs_restrict" ) ) {
		char keywords[MAX_INFO_STRING];

		Com_sprintf( keywords, sizeof( keywords ), "demo %s",
					 Info_ValueForKey( infostring, "sv_keywords" ) );
		Info_SetValueForKey( infostring, "sv_keywords", keywords );
	}

	status[0] = 0;
	statusLength = 0;

	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
		cl = &svs.clients[i];
		if ( cl->state >= CS_CONNECTED ) {
			ps = SV_GameClientNum( i );
			Com_sprintf( player, sizeof( player ), "%i %i \"%s\"\n",
						 ps->persistant[PERS_SCORE], cl->ping, cl->name );
			playerLength = strlen( player );
			if ( statusLength + playerLength >= sizeof( status ) ) {
				break;      // can't hold any more
			}
			strcpy( status + statusLength, player );
			statusLength += playerLength;
		}
	}

	NET_OutOfBandPrint( NS_SERVER, from, "statusResponse\n%s\n%s", infostring, status );
}
示例#6
0
/*
====================
SV_ClientStatus_f
Joe Kari: New admin command that provide tons of information about everyone.
====================
*/
static void SV_ClientStatus_f( void ) {
	int			i;
	client_t	*cl;
	const char		*s;
	playerState_t	*ps;
	int			ping;
	
	// Move to g_svcmds.c

	// make sure server is running
	if ( !com_sv_running->integer ) {
		Com_Printf( "Server is not running.\n" );
		return;
	}
	
	
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
			continue;
		
		ps = SV_GameClientNum( i );
		
		// ID
		Com_Printf ("^5*** ID^7:%i  ", i);
		// Name
		Com_Printf ("^5name^7:%s^7\n", cl->name);
		
		// IP (or: loopback or bot)
		s = NET_AdrToString( cl->netchan.remoteAddress );
		Com_Printf ("^3IP^7:%s ", s);
		// GUID
		s = Info_ValueForKey (cl->userinfo, "cl_guid");
		if (Q_stricmp (s, "") == 0)  s = "<null>" ;
		Com_Printf ("^3GUID^7:%s\n", s);
		
		// Ping
		if (cl->state == CS_CONNECTED)
			Com_Printf ("^6ping^7:CONNECTED ");
		else if (cl->state == CS_ZOMBIE)
			Com_Printf ("^6ping^7:ZOMBIE ");
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf ("^6ping^7:%i ", ping);
		}
		
		// Rate
		Com_Printf ("^6rate^7:%i ", cl->rate);
		
		// Port
		Com_Printf ("^6port^7:%i\n", cl->netchan.qport);
	}
}
示例#7
0
/*
================
SVC_Status

Responds with all the info that qplug or qspy can see about the server
and all connected players.  Used for getting detailed information after
the simple info query.
================
*/
void SVC_Status( netadr_t from, const Cmd::Args& args )
{
	char          player[ 1024 ];
	char          status[ MAX_MSGLEN ];
	int           i;
	client_t      *cl;
	playerState_t *ps;
	int           statusLength;
	int           playerLength;
	char          infostring[ MAX_INFO_STRING ];

	//bani - bugtraq 12534
	if ( args.Argc() > 1 && !SV_VerifyChallenge( args.Argv(1).c_str() ) )
	{
		return;
	}

	Q_strncpyz( infostring, Cvar_InfoString( CVAR_SERVERINFO, false ), MAX_INFO_STRING );

	if ( args.Argc() > 1 )
	{
		// echo back the parameter to status. so master servers can use it as a challenge
		// to prevent timed spoofed reply packets that add ghost servers
		Info_SetValueForKey( infostring, "challenge", args.Argv(1).c_str(), false );
	}

	status[ 0 ] = 0;
	statusLength = 0;

	for ( i = 0; i < sv_maxclients->integer; i++ )
	{
		cl = &svs.clients[ i ];

		if ( cl->state >= CS_CONNECTED )
		{
			ps = SV_GameClientNum( i );
			Com_sprintf( player, sizeof( player ), "%i %i \"%s\"\n", ps->persistant[ PERS_SCORE ], cl->ping, cl->name );
			playerLength = strlen( player );

			if ( statusLength + playerLength >= (int) sizeof( status ) )
			{
				break; // can't hold any more
			}

			strcpy( status + statusLength, player );
			statusLength += playerLength;
		}
	}

	NET_OutOfBandPrint( NS_SERVER, from, "statusResponse\n%s\n%s", infostring, status );
}
示例#8
0
static void SV_NetStatus_f(void) {
	char			netStatus[4096] = {0};
	int				i;
	char			cleanName[MAX_NETNAME] = {0};
	client_t		*cl;
	playerState_t	*ps;

	Q_strcat(netStatus, sizeof(netStatus), "\n");

	Q_strcat(netStatus, sizeof(netStatus), "ID Score Ping Name            LastMSG Address               QPort Rate\n");
	Q_strcat(netStatus, sizeof(netStatus), "-- ----- ---- --------------- ------- --------------------- ----- -----\n");
	
	for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++)
	{
		if (!cl->state)
		{
			continue;
		}
		
		Q_strcat(netStatus, sizeof(netStatus), va("%2i ", i)); //ID
		
		ps = SV_GameClientNum(i);

		Q_strcat(netStatus, sizeof(netStatus), va("%5i ", ps->persistant[PERS_SCORE])); //Score

		if (cl->state == CS_CONNECTED)
			Q_strcat(netStatus, sizeof(netStatus), "CNCT "); //Ping
		else if (cl->state == CS_ZOMBIE)
			Q_strcat(netStatus, sizeof(netStatus), "ZMBI "); //Ping
		else
			Q_strcat(netStatus, sizeof(netStatus), va("%4i ", cl->ping < 999 ? cl->ping : 999)); //Ping

		//FIXME: stripcolor until we fix alignment
		Q_strncpyz(cleanName, cl->name, sizeof(cleanName));
		Q_StripColor(cleanName);

		Q_strcat(netStatus, sizeof(netStatus), va("%-15.15s ", cleanName)); //Name
		Q_strcat(netStatus, sizeof(netStatus), va("%7i ", svs.time - cl->lastPacketTime)); //LastMSG
		Q_strcat(netStatus, sizeof(netStatus), va("%21s ", NET_AdrToString(cl->netchan.remoteAddress))); //Address
		Q_strcat(netStatus, sizeof(netStatus), va("%5i ", cl->netchan.qport)); //QPort
		Q_strcat(netStatus, sizeof(netStatus), va("%5i ", cl->rate)); //Rate
	}
	Q_strcat(netStatus, sizeof(netStatus), "\n");

	Com_Printf(netStatus);
}
示例#9
0
/*
===================
SV_CalcPings

Updates the cl->ping variables
===================
*/
void SV_CalcPings( void ) {
	int			i, j;
	client_t	*cl;
	int			total, count;
	int			delta;
	playerState_t	*ps;

	for (i=0 ; i < sv_maxclients->integer ; i++) {
		cl = &svs.clients[i];
		if ( cl->state != CS_ACTIVE ) {
			cl->ping = 999;
			continue;
		}
		if ( !cl->gentity ) {
			cl->ping = 999;
			continue;
		}

		total = 0;
		count = 0;
		for ( j = 0 ; j < PACKET_BACKUP ; j++ ) {
			if ( cl->frames[j].messageAcked <= 0 ) {
				continue;
			}
			delta = cl->frames[j].messageAcked - cl->frames[j].messageSent;
			count++;
			total += delta;
		}
		if (!count) {
			cl->ping = 999;
		} else {
			cl->ping = total/count;
			if ( cl->ping > 999 ) {
				cl->ping = 999;
			}
		}

		// let the game dll know about the ping
		ps = SV_GameClientNum( i );
		ps->ping = cl->ping;
	}
}
示例#10
0
文件: sv_demo.c 项目: dioda/apb
void SV_WriteDemoArchive(msg_t *msg, client_t *client){

	int archiveIndex;
	playerState_t *ps = SV_GameClientNum(client - svs.clients);
	vec3_t nullvec = {0, 0, 0};

	MSG_WriteByte(msg, 1);

	archiveIndex = client->demoArchiveIndex % 256;
	MSG_WriteLong(msg, archiveIndex);
	MSG_WriteVector(msg, ps->origin);

	MSG_WriteVector(msg, nullvec);
	MSG_WriteLong(msg, 0); //Velocity

	MSG_WriteLong(msg, 0);
	MSG_WriteLong(msg, ps->commandTime);
	MSG_WriteVector(msg, ps->viewangles);
	client->demoArchiveIndex++;

}
示例#11
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f(void)
{
	int           i, j, l;
	client_t      *cl;
	playerState_t *ps;
	const char    *s;
	int           ping;

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

	Com_Printf("cpu server utilization: %i %%\n"
	           "avg response time     : %i ms\n"
	           "server time           : %i\n"
	           "internal time         : %i\n"
	           "map                   : %s\n\n"
	           "num score ping name            lastmsg address               qport rate\n"
	           "--- ----- ---- --------------- ------- --------------------- ----- -----\n",
	           ( int ) svs.stats.cpu,
	           ( int ) svs.stats.avg,
	           svs.time,
	           Sys_Milliseconds(),
	           sv_mapname->string);

	// FIXME: extend player name length (>16 chars) ? - they are printed!
	// FIXME: do a Com_Printf per line! ... create the row at first
	for (i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++)
	{
		if (!cl->state && !cl->demoClient)
		{
			continue;
		}
		Com_Printf("%3i ", i);
		ps = SV_GameClientNum(i);
		Com_Printf("%5i ", ps->persistant[PERS_SCORE]);

		if (cl->demoClient) // if it's a democlient, we show DEMO instead of the ping (which would be 999 anyway - which is not the case in the scoreboard which show the real ping that had the player because commands are replayed!)
		{
			Com_Printf("DEMO ");
		}
		else if (cl->state == CS_CONNECTED)
		{
			Com_Printf("CNCT ");
		}
		else if (cl->state == CS_ZOMBIE)
		{
			Com_Printf("ZMBI ");
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf("%4i ", ping);
		}

		Com_Printf("%s", rc(cl->name));
		l = 16 - strlen(cl->name);
		for (j = 0 ; j < l ; j++)
		{
			Com_Printf(" ");
		}

		Com_Printf("%7i ", svs.time - cl->lastPacketTime);

		s = NET_AdrToString(cl->netchan.remoteAddress);
		Com_Printf("%s", s);

		l = 22 - strlen(s);
		for (j = 0 ; j < l ; j++)
		{
			Com_Printf(" ");
		}

		Com_Printf("%5i", cl->netchan.qport);

		Com_Printf(" %5i\n", cl->rate);
	}

	Com_Printf("\n");
}
示例#12
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void ) 
{
	int				i, humans, bots;
	client_t		*cl;
	playerState_t	*ps;
	const char		*s;
	int				ping;
	char			state[32];
	qboolean		avoidTruncation = qfalse;

	// make sure server is running
	if ( !com_sv_running->integer ) 
	{
		//Ensiform: Why raven why, you didn't do this in other cmds.
		Com_Printf( "Server is not running.\n" );
		//Com_Printf( SE_GetString("STR_SERVER_SERVER_NOT_RUNNING") );
		return;
	}

	if ( Cmd_Argc() > 1 )
	{
		if (!Q_stricmp("notrunc", Cmd_Argv(1)))
		{
			avoidTruncation = qtrue;
		}
	}

	humans = bots = 0;
	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
		if ( svs.clients[i].state >= CS_CONNECTED ) {
			if ( svs.clients[i].netchan.remoteAddress.type != NA_BOT ) {
				humans++;
			}
			else {
				bots++;
			}
		}
	}

#if defined(_WIN32)
#define STATUS_OS "Windows"
#elif defined(__linux__)
#define STATUS_OS "Linux"
#elif defined(MACOS_X)
#define STATUS_OS "OSX"
#else
#define STATUS_OS "Unknown"
#endif

	const char *ded_table[] = 
	{
		"listen",
		"lan dedicated",
		"public dedicated",
	};

	Com_Printf ("hostname: %s\n", sv_hostname->string );
	Com_Printf ("version : %s %i\n", VERSION_STRING_DOTTED, PROTOCOL_VERSION );
	Com_Printf ("game    : %s\n", FS_GetCurrentGameDir() );
	Com_Printf ("udp/ip  : %s:%i os(%s) type(%s)\n", Cvar_VariableString("net_ip"), Cvar_VariableIntegerValue("net_port"), STATUS_OS, ded_table[com_dedicated->integer]);
	Com_Printf ("map     : %s gametype(%i)\n", sv_mapname->string, sv_gametype->integer );
	Com_Printf ("players : %i humans, %i bots (%i max)\n", humans, bots, sv_maxclients->integer - sv_privateClients->integer);

	Com_Printf ("num score ping name            lastmsg address               qport rate\n");
	Com_Printf ("--- ----- ---- --------------- ------- --------------------- ----- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
		{
			continue;
		}

		if (cl->state == CS_CONNECTED)
		{
			strcpy(state, "CNCT ");
		}
		else if (cl->state == CS_ZOMBIE)
		{
			strcpy(state, "ZMBI ");
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_sprintf(state, sizeof(state), "%4i", ping);
		}

		ps = SV_GameClientNum( i );
		s = NET_AdrToString( cl->netchan.remoteAddress );

		if (!avoidTruncation)
		{
			Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n", 
				i, 
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				svs.time - cl->lastPacketTime,
				s,
				cl->netchan.qport,
				cl->rate
				);
		}
		else
		{
			Com_Printf ("%3i %5i %s %s %7i %21s %5i %5i\n", 
				i, 
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				svs.time - cl->lastPacketTime,
				s,
				cl->netchan.qport,
				cl->rate
				);
		}
	}
	Com_Printf ("\n");
}
示例#13
0
/*
 * Tests whether the player entity ent is visible from the point origin.
 */
qboolean SV_IsPlayerVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, sharedEntity_t *ent, vec3_t diff) {
	int      i,contents_mask,goal_ent,viewer_clnum,ent_clnum,tries;
	trace_t   tr;
	vec3_t   start,end,dir,entangles,angles,temp,forward;
	sharedEntity_t *viewer_ent;
	client_t *viewer_cl;
//	client_t *ent_cl;
	playerState_t *viewer_ps, *ent_ps;
	float pitch;

	viewer_clnum = frame->ps.clientNum; // get the client number of the viewer
	ent_clnum = ent->s.clientNum; // get the client number of the other player

	if (viewer_clnum == ent_clnum) { // in case the viewer is the player entity
		return qtrue; // we don't need to hide us from ourselves
	}

	viewer_ps = &frame->ps;
	ent_ps = SV_GameClientNum(ent_clnum);

	if (viewer_ps->pm_type != PM_NORMAL) { // if the viewer is dead or spectating
		return qtrue; // let every entity be visible
	}

	if (ent_ps->pm_type != PM_NORMAL || (ent->s.weapon == WP_NONE)) { // if the player entity is dead or spectating
		return qtrue;
	}

	viewer_cl = svs.clients+viewer_clnum; // get the client of the viewer
//	ent_cl = svs.clients+ent_clnum; // get the client of the other player

//	if (viewer_clnum > ent_clnum) { // if viewer_clnum > ent_clnum, we have already tested whether ent_clnum is able to see viewer_clnum.
//		if (ent_cl->tracetimer[viewer_clnum] > sv.time) return qtrue; // and we could assume symmetry of SV_IsPlayerVisibleFromPoint
//	}

	if (viewer_cl->tracetimer[ent_clnum] > sv.time+MEMORY+10) { // if the sv.time has been reset
		viewer_cl->tracetimer[ent_clnum] = sv.time; // reset the tracetimer
	} else if (viewer_cl->tracetimer[ent_clnum] > (sv.time+MEMORY-10)) { // if we have recently seen this entity, we are lazy and assume it is still visible
		// Com_Printf(va("client: %i, seen: %i\n", ent_clnum, viewer_cl->tracetimer[ent_clnum]));
		return qtrue;
	}

	goal_ent = SV_NumForGentity(ent); // this might always be the same as ent_clnum
	viewer_ent = SV_GentityNum(viewer_clnum);
	contents_mask = CONTENTS_SOLID;// |CONTENTS_BODY will work for doors, but also for windows  |CONTENTS_PLAYERCLIP|CONTENTS_SOLID|CONTENTS_MOVER|CONTENTS_PLAYERCLIP

//	if (seen->v.movetype == MOVETYPE_PUSH ) { //don't cull doors and plats :(
//		return false;
//	}

//	if (sv_antiwallhack.value == 1)    //1 only check player models, 2 = check all ents
//	if (strcmp(pr_strings + seen->v.classname, "player"))
//	return qfalse;

	// get camera origin (according to \cg_drawdebug 1)
	start[0] = origin[0];
	start[1] = origin[1];
	start[2] = origin[2]+3.0f;
	VectorCopy(viewer_ps->viewangles, angles);
	AnglesNormalize180(angles);
	pitch = angles[PITCH];
	angles[PITCH] = 0;
	angles[ROLL] = 0;
	AngleVectors(angles, forward, NULL, NULL);
	VectorScale(forward, (pitch/3.5f), temp);
	VectorAdd( start, temp, start);

	// if there is sufficient distance between viewer and player entity, check if player entity is within viewer's field of vision
	VectorSubtract(ent->r.currentOrigin, start, dir);
//	VectorAdd(ent->r.currentOrigin,dir,diff);// fill diff
	VectorCopy(viewer_ent->s.pos.trBase,diff);// fill diff
	vectoangles(dir, entangles);
	dir[2]=0; // pretend, players are on the same level (the height should no be taken into account)
	if (VectorLength(dir) > 1024) {// if it is not within close range (x,y-wise, not z-wise)
		if (!InFieldOfVision(viewer_ps->viewangles, 60.f, entangles, ent_clnum)) {// If the player entity is not in the field of vision of the viewer
//			 Com_Printf( va("behind: %i  vorg: %f,%f,%f  vang: %f,%f,%f  eorg: %f,%f,%f  dir: %f,%f,%f  eang: %f,%f,%f  ent: %i\n", viewer_clnum,origin[0],origin[1],origin[2],viewer_ps->viewangles[0],viewer_ps->viewangles[1],viewer_ps->viewangles[2],ent->r.currentOrigin[0],ent->r.currentOrigin[1],ent->r.currentOrigin[2],dir[0],dir[1],dir[2],entangles[0],entangles[1],entangles[2],ent_clnum));
			return qtrue; // if the player entity is behind the viewer, abstain from any computations (and transmit the entity to hear sounds)
//		} else {
//			 Com_Printf( va("front: %i  vorg: %f,%f,%f  vang: %f,%f,%f  eorg: %f,%f,%f  dir: %f,%f,%f  eang: %f,%f,%f  ent: %i\n", viewer_clnum,origin[0],origin[1],origin[2],viewer_ps->viewangles[0],viewer_ps->viewangles[1],viewer_ps->viewangles[2],ent->r.currentOrigin[0],ent->r.currentOrigin[1],ent->r.currentOrigin[2],dir[0],dir[1],dir[2],entangles[0],entangles[1],entangles[2],ent_clnum));
		}
	}

	// aim straight at the head of the entity from our eyes
	end[0] = ent->r.currentOrigin[0];
	end[1] = ent->r.currentOrigin[1];
	end[2] = ent->r.currentOrigin[2]+ent->r.maxs[2];// "+3.0f" doesn't do it. "+ent->r.maxs[2]" is at the top of the BBox
	VectorCopy(ent_ps->viewangles, angles);
	AnglesNormalize180(angles);
	pitch = angles[PITCH];
	angles[PITCH] = 0;
	angles[ROLL] = 0;
	AngleVectors(angles, forward, NULL, NULL);
	VectorScale(forward, (pitch/3.5f), temp);
	VectorAdd( end, temp, end);



	memset (&tr, 0, sizeof(tr));
	tr.fraction = 1;

	// check the head
	SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
	// Com_Printf(va("client: %i, trace: %f\n", ent->s.clientNum, tr.fraction));
	if (tr.fraction == 1 || tr.entityNum==goal_ent) {// tr.fraction == 1 || if there is a line of sight to the entity
		viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
		return qtrue;// and signal the entity is visible
	}
	// Com_Printf(va("origin(%f %f %f) min(%f %f %f) max(%f %f %f)\n", start[0], start[1], start[2], mins[0],mins[1],mins[2],maxs[0],maxs[1],maxs[2]));

	// check the last good offset
	VectorAdd(ent->r.currentOrigin,viewer_cl->lasttrace[ent_clnum],end);
	SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
	// Com_Printf(va("client: %i, trace: %f\n", ent->s.clientNum, tr.fraction));
	if (tr.fraction == 1 || tr.entityNum==goal_ent) {// tr.fraction == 1 || if there is a line of sight to the entity
		viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
		return qtrue;// and signal the entity is visible
	}

	// random
	tries = (viewer_cl->tracetimer[ent_clnum]+(MEMORY*20) > sv.time)?8:2;// if we have seen an entity recently, we try hard to locate it again
	for (i=0; i<tries; i++) {// Even if the head is not visible, other body parts might be. Let's check a few randomly selected points
		end[0] = ent->r.currentOrigin[0] + offsetrandom(ent->r.mins[0], ent->r.maxs[0]);
		end[1] = ent->r.currentOrigin[1] + offsetrandom(ent->r.mins[1], ent->r.maxs[1]);
		end[2] = ent->r.currentOrigin[2] + offsetrandom(ent->r.mins[2], ent->r.maxs[2]+3.f);

		SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
		if (tr.fraction == 1 || tr.entityNum==goal_ent) {//  if there is a line of sight to the entity
			// Com_Printf(va("found ent in %i hits\n", i));
			viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
			VectorSubtract(end, ent->r.currentOrigin, viewer_cl->lasttrace[ent_clnum]);// remember the offset
			return qtrue;// and signal the entity is visible
		}
	}

	viewer_cl->lasttrace[ent_clnum][0] = offsetrandom(ent->r.mins[0], ent->r.maxs[0]);
	viewer_cl->lasttrace[ent_clnum][1] = offsetrandom(ent->r.mins[1], ent->r.maxs[1]);
	viewer_cl->lasttrace[ent_clnum][2] = offsetrandom(ent->r.mins[2], ent->r.maxs[2]+3.f);

	return (viewer_cl->tracetimer[ent_clnum] > sv.time);// returns true if the entity was visible within the last 200 time units
}
示例#14
0
文件: sv_ccmds.c 项目: Pan7/ioq3df
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void ) {
	int			i, j, l;
	client_t	*cl;
	playerState_t	*ps;
	const char		*s;
	int			ping;

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

	Com_Printf ("map: %s\n", sv_mapname->string );

	Com_Printf ("cl score ping name            address                                 rate \n");
	Com_Printf ("-- ----- ---- --------------- --------------------------------------- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
			continue;
		Com_Printf ("%2i ", i);
		ps = SV_GameClientNum( i );
		Com_Printf ("%5i ", ps->persistant[PERS_SCORE]);

		if (cl->state == CS_CONNECTED)
			Com_Printf ("CON ");
		else if (cl->state == CS_ZOMBIE)
			Com_Printf ("ZMB ");
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf ("%4i ", ping);
		}

		Com_Printf ("%s", cl->name);
		
		l = 16 - SV_Strlen(cl->name);
		j = 0;
		
		do
		{
			Com_Printf (" ");
			j++;
		} while(j < l);


		// TTimo adding a ^7 to reset the color
		s = NET_AdrToString( cl->netchan.remoteAddress );
		Com_Printf ("^7%s", s);
		l = 39 - strlen(s);
		j = 0;
		
		do
		{
			Com_Printf(" ");
			j++;
		} while(j < l);
		
		Com_Printf (" %5i", cl->rate);

		Com_Printf ("\n");
	}
	Com_Printf ("\n");
}
示例#15
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void )
{
	int           i, j, l;
	client_t      *cl;
	playerState_t *ps;
	const char    *s;
	int           ping;
	float         cpu, avg;

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

	cpu = ( svs.stats.latched_active + svs.stats.latched_idle );

	if ( cpu )
	{
		cpu = 100 * svs.stats.latched_active / cpu;
	}

	avg = 1000 * svs.stats.latched_active / STATFRAMES;

	Com_Printf( "cpu utilization  : %3i%%\n"
	            "avg response time: %i ms\n"
	            "map: %s\n"
	            "num score ping name            lastmsg address               qport rate\n"
	            "--- ----- ---- --------------- ------- --------------------- ----- -----\n",
	           ( int ) cpu, ( int ) avg, sv_mapname->string );

	for ( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
	{
		if ( !cl->state )
		{
			continue;
		}

		Com_Printf( "%3i ", i );
		ps = SV_GameClientNum( i );
		Com_Printf( "%5i ", ps->persistant[ PERS_SCORE ] );

		if ( cl->state == CS_CONNECTED )
		{
			Com_Printf( "CNCT " );
		}
		else if ( cl->state == CS_ZOMBIE )
		{
			Com_Printf( "ZMBI " );
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf( "%4i ", ping );
		}

		Com_Printf( "%s", cl->name );
		l = 16 - strlen( cl->name );

		for ( j = 0; j < l; j++ )
		{
			Com_Printf( " " );
		}

		Com_Printf( "%7i ", svs.time - cl->lastPacketTime );

		s = NET_AdrToString( cl->netchan.remoteAddress );
		Com_Printf( "%s", s );
		l = 22 - strlen( s );

		for ( j = 0; j < l; j++ )
		{
			Com_Printf( " " );
		}

		Com_Printf( "%5i", cl->netchan.qport );

		Com_Printf( " %5i", cl->rate );

		Com_Printf( "\n" );
	}

	Com_Printf( "\n" );
}
示例#16
0
文件: sv_ccmds.cpp 项目: vvvjk2/jk2mv
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void )
{
	int				i;
	client_t		*cl;
	playerState_t	*ps;
	const char		*s;
	int				ping;
	char			state[32];
	qboolean		avoidTruncation = qfalse;

	int				j, k;
	char			spaces[32];
	char			displayName[MAX_NAME_LENGTH];

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

	if ( Cmd_Argc() > 1 )
	{
		if (!Q_stricmp("notrunc", Cmd_Argv(1)))
		{
			avoidTruncation = qtrue;
		}
	}

	Com_Printf ("map: %s\n", sv_mapname->string );

	Com_Printf ("num score ping name            lastmsg address               qport rate\n");
	Com_Printf ("--- ----- ---- --------------- ------- --------------------- ----- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
		{
			continue;
		}

		if (cl->state == CS_CONNECTED)
		{
			strcpy(state, "CNCT ");
		}
		else if (cl->state == CS_ZOMBIE)
		{
			strcpy(state, "ZMBI ");
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			sprintf(state, "%4i", ping);
		}

		ps = SV_GameClientNum( i );
		s = NET_AdrToString( cl->netchan.remoteAddress );

		// Count the length of the visible characters in the name and if it's less than 15 fill the rest with spaces
		k = MV_StrlenSkipColors(cl->name);
		if ( k < 0 ) k = 0; // Should never happen
		for( j = 0; j < (15 - k); j++ ) spaces[j] = ' ';
		spaces[j] = 0;

		if (!avoidTruncation) MV_CopyStringWithColors( cl->name, displayName, sizeof(displayName), 15 ); // Limit the visible length of the name to 15 characters (not counting colors)
		else				  Q_strncpyz( displayName, cl->name, sizeof(displayName) );

		Com_Printf ("%3i %5i %s %s^7%s %7i %21s %5i %5i\n",
			i,
			ps->persistant[PERS_SCORE],
			state,
			displayName,
			spaces,
			svs.time - cl->lastPacketTime,
			s,
			cl->netchan.qport,
			cl->rate
			);
	}
	Com_Printf ("\n");
}
示例#17
0
int SV_CanSee(int player, int other)
{
	sharedEntity_t *pent, *oent;
	playerState_t  *ps;
	vec3_t         viewpoint, tmp;
	int            i;

	// check if bounding box has been changed
	if (sv_wh_bbox_horz->integer != bbox_horz)
	{
		init_horz_delta();
	}

	if (sv_wh_bbox_vert->integer != bbox_vert)
	{
		init_vert_delta();
	}

	ps   = SV_GameClientNum(player);
	pent = SV_GentityNum(player);
	oent = SV_GentityNum(other);

	// check if 'other' is in the maximum fov allowed
	if (sv_wh_check_fov->integer > 0)
	{
		if (!player_in_fov(pent->s.apos.trBase, pent->s.pos.trBase, oent->s.pos.trBase))
		{
			return 0;
		}
	}

	// check if visible in this frame
	calc_viewpoint(ps, pent->s.pos.trBase, viewpoint);

	for (i = 0; i < 8; i++)
	{
		VectorCopy(oent->s.pos.trBase, tmp);
		tmp[0] += delta[i][0];
		tmp[1] += delta[i][1];
		tmp[2] += delta[i][2] + VOFS;

		if (is_visible(viewpoint, tmp))
		{
			return 1;
		}
	}

	// predict player positions
	copy_trajectory(&pent->s.pos, &traject);
	predict_move(pent, PREDICT_TIME, &traject, pred_ppos);

	copy_trajectory(&oent->s.pos, &traject);
	predict_move(oent, PREDICT_TIME, &traject, pred_opos);

	// Check again if 'other' is in the maximum fov allowed.
	// FIXME: We use the original viewangle that may have
	// changed during the move. This could introduce some
	// errors.
	if (sv_wh_check_fov->integer > 0)
	{
		if (!player_in_fov(pent->s.apos.trBase, pred_ppos, pred_opos))
		{
			return 0;
		}
	}

	// check if expected to be visible in the next frame
	calc_viewpoint(ps, pred_ppos, viewpoint);

	for (i = 0; i < 8; i++)
	{
		VectorCopy(pred_opos, tmp);
		tmp[0] += delta[i][0];
		tmp[1] += delta[i][1];
		tmp[2] += delta[i][2] + VOFS;

		if (is_visible(viewpoint, tmp))
		{
			return 1;
		}
	}

	return 0;
}
示例#18
0
/*
=============
SV_BuildClientSnapshot

Decides which entities are going to be visible to the client, and
copies off the playerstate and areabits.

This properly handles multiple recursive portals, but the render
currently doesn't.

For viewing through other player's eyes, clent can be something other than client->gentity
=============
*/
static void SV_BuildClientSnapshot( client_t *client ) {
	vec3_t						org;
	clientSnapshot_t			*frame;
	snapshotEntityNumbers_t		entityNumbers;
	int							i;
	sharedEntity_t				*ent;
	entityState_t				*state;
	svEntity_t					*svEnt;
	sharedEntity_t				*clent;
	playerState_t				*ps;

	// bump the counter used to prevent double adding
	sv.snapshotCounter++;

	// this is the frame we are creating
	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];

	// clear everything in this snapshot
	entityNumbers.numSnapshotEntities = 0;
	Com_Memset( frame->areabits, 0, sizeof( frame->areabits ) );

	frame->num_entities = 0;

	clent = client->gentity;
	if ( !clent || client->state == CS_ZOMBIE ) {
		return;
	}

	// grab the current playerState_t
	ps = SV_GameClientNum( client - svs.clients );
	frame->ps = *ps;
#ifdef _ONEBIT_COMBO
	frame->pDeltaOneBit = &ps->deltaOneBits;
	frame->pDeltaNumBit = &ps->deltaNumBits;
#endif

	if (ps->m_iVehicleNum)
	{ //get the vehicle's playerstate too then
		sharedEntity_t *veh = SV_GentityNum(ps->m_iVehicleNum);

		if (veh && veh->playerState)
		{ //Now VMA it and we've got ourselves a playerState
			playerState_t *vps = ((playerState_t *)VM_ArgPtr((int)veh->playerState));

            frame->vps = *vps;
#ifdef _ONEBIT_COMBO
			frame->pDeltaOneBitVeh = &vps->deltaOneBits;
			frame->pDeltaNumBitVeh = &vps->deltaNumBits;
#endif
		}
	}

	int							clientNum;
	// never send client's own entity, because it can
	// be regenerated from the playerstate
	clientNum = frame->ps.clientNum;
	if ( clientNum < 0 || clientNum >= MAX_GENTITIES ) {
		Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" );
	}
	svEnt = &sv.svEntities[ clientNum ];
	svEnt->snapshotCounter = sv.snapshotCounter;

	
	// find the client's viewpoint
	VectorCopy( ps->origin, org );
	org[2] += ps->viewheight;

	// add all the entities directly visible to the eye, which
	// may include portal entities that merge other viewpoints
	SV_AddEntitiesVisibleFromPoint( org, frame, &entityNumbers, qfalse );

	// if there were portals visible, there may be out of order entities
	// in the list which will need to be resorted for the delta compression
	// to work correctly.  This also catches the error condition
	// of an entity being included twice.
	qsort( entityNumbers.snapshotEntities, entityNumbers.numSnapshotEntities, 
		sizeof( entityNumbers.snapshotEntities[0] ), SV_QsortEntityNumbers );

	// now that all viewpoint's areabits have been OR'd together, invert
	// all of them to make it a mask vector, which is what the renderer wants
	for ( i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++ ) {
		((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
	}

	// copy the entity states out
	frame->num_entities = 0;
	frame->first_entity = svs.nextSnapshotEntities;
	for ( i = 0 ; i < entityNumbers.numSnapshotEntities ; i++ ) {
		ent = SV_GentityNum(entityNumbers.snapshotEntities[i]);
		state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
		*state = ent->s;
		svs.nextSnapshotEntities++;
		// this should never hit, map should always be restarted first in SV_Frame
		if ( svs.nextSnapshotEntities >= 0x7FFFFFFE ) {
			Com_Error(ERR_FATAL, "svs.nextSnapshotEntities wrapped");
		}
		frame->num_entities++;
	}
}
示例#19
0
/*
=============
SV_BuildClientSnapshot

Decides which entities are going to be visible to the client, and
copies off the playerstate and areabits.

This properly handles multiple recursive portals, but the render
currently doesn't.

For viewing through other player's eyes, clent can be something other than client->gentity
=============
*/
static void SV_BuildClientSnapshot( client_t* client )
{
	vec3_c                      org;
	clientSnapshot_t*           frame;
	snapshotEntityNumbers_t     entityNumbers;
	int                         i;
	edict_s*                ent;
	entityState_s*              state;
	svEntity_t*                 svEnt;
	edict_s*                clent;
	int                         clientNum;
	playerState_s*              ps;
	
	// bump the counter used to prevent double adding
	sv.snapshotCounter++;
	
	// this is the frame we are creating
	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
	
	// clear everything in this snapshot
	entityNumbers.numSnapshotEntities = 0;
	memset( frame->areabits, 0, sizeof( frame->areabits ) );
	
	// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=62
	frame->num_entities = 0;
	
	clent = client->gentity;
	if ( !clent || client->state == CS_ZOMBIE )
	{
		return;
	}
	
	// grab the current playerState_s
	ps = SV_GameClientNum( client - svs.clients );
	frame->ps = *ps;
	
	// never send client's own entity, because it can
	// be regenerated from the playerstate
	clientNum = frame->ps.clientNum;
	if ( clientNum < 0 || clientNum >= MAX_GENTITIES )
	{
		Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" );
	}
	svEnt = &sv.svEntities[ clientNum ];
	
	svEnt->snapshotCounter = sv.snapshotCounter;
	
	// find the client's viewpoint
	org = ps->origin;
	org[2] += ps->viewheight;
	
	// add all the entities directly visible to the eye, which
	// may include portal entities that merge other viewpoints
	bitSet_c areaBits;
	if ( sv_bsp )
	{
		areaBits.init( sv_bsp->getNumAreas(), false );
	}
	SV_AddEntitiesVisibleFromPoint( org, frame, &entityNumbers, false, areaBits );
	
	memcpy( frame->areabits, areaBits.getArray(), areaBits.getSizeInBytes() );
	frame->areabytes = areaBits.getSizeInBytes();
	
	// if there were portals visible, there may be out of order entities
	// in the list which will need to be resorted for the delta compression
	// to work correctly.  This also catches the error condition
	// of an entity being included twice.
	qsort( entityNumbers.snapshotEntities, entityNumbers.numSnapshotEntities,
		   sizeof( entityNumbers.snapshotEntities[0] ), SV_QsortEntityNumbers );
		   
	// now that all viewpoint's areabits have been OR'd together, invert
	// all of them to make it a mask vector, which is what the renderer wants
	for ( i = 0 ; i < MAX_MAP_AREA_BYTES / 4 ; i++ )
	{
		( ( int* )frame->areabits )[i] = ( ( int* )frame->areabits )[i] ^ -1;
	}
	
	// copy the entity states out
	frame->num_entities = 0;
	frame->first_entity = svs.nextSnapshotEntities;
	for ( i = 0 ; i < entityNumbers.numSnapshotEntities ; i++ )
	{
		ent = SV_GentityNum( entityNumbers.snapshotEntities[i] );
		state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
		// copy entityState_s from entity/player
		*state = *ent->s;
		svs.nextSnapshotEntities++;
		// this should never hit, map should always be restarted first in SV_Frame
		if ( svs.nextSnapshotEntities >= 0x7FFFFFFE )
		{
			Com_Error( ERR_FATAL, "svs.nextSnapshotEntities wrapped" );
		}
		frame->num_entities++;
	}
}
示例#20
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void )
{
	int				i, humans, bots;
	client_t		*cl;
	playerState_t	*ps;
	const char		*s;
	int				ping;
	char			state[32];
	qboolean		avoidTruncation = qfalse;

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

	if ( Cmd_Argc() > 1 )
	{
		if (!Q_stricmp("notrunc", Cmd_Argv(1)))
		{
			avoidTruncation = qtrue;
		}
	}

	humans = bots = 0;
	for ( i = 0 ; i < sv_maxclients->integer ; i++ ) {
		if ( svs.clients[i].state >= CS_CONNECTED ) {
			if ( svs.clients[i].netchan.remoteAddress.type != NA_BOT ) {
				humans++;
			}
			else {
				bots++;
			}
		}
	}

#if defined(_WIN32)
#define STATUS_OS "Windows"
#elif defined(__linux__)
#define STATUS_OS "Linux"
#elif defined(MACOS_X)
#define STATUS_OS "OSX"
#else
#define STATUS_OS "Unknown"
#endif

	const char *ded_table[] =
	{
		"listen",
		"lan dedicated",
		"public dedicated",
	};

	char hostname[MAX_HOSTNAMELENGTH] = { 0 };

	Q_strncpyz( hostname, sv_hostname->string, sizeof(hostname) );
	Q_StripColor( hostname );

	Com_Printf( "hostname: %s^7\n", hostname );
	Com_Printf( "version : %s %i\n", VERSION_STRING_DOTTED, PROTOCOL_VERSION );
	Com_Printf( "game    : %s\n", FS_GetCurrentGameDir() );
	Com_Printf( "udp/ip  : %s:%i os(%s) type(%s)\n", Cvar_VariableString( "net_ip" ), Cvar_VariableIntegerValue( "net_port" ), STATUS_OS, ded_table[com_dedicated->integer] );
	Com_Printf( "map     : %s gametype(%i)\n", sv_mapname->string, sv_gametype->integer );
	Com_Printf( "players : %i humans, %i bots (%i max)\n", humans, bots, sv_maxclients->integer - sv_privateClients->integer );
	Com_Printf( "uptime  : %s\n", SV_CalcUptime() );

	Com_Printf ("cl score ping name            address                                 rate \n");
	Com_Printf ("-- ----- ---- --------------- --------------------------------------- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if ( !cl->state )
			continue;

		if ( cl->state == CS_CONNECTED )
			Q_strncpyz( state, "CON ", sizeof( state ) );
		else if ( cl->state == CS_ZOMBIE )
			Q_strncpyz( state, "ZMB ", sizeof( state ) );
		else {
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_sprintf( state, sizeof(state), "%4i", ping );
		}

		ps = SV_GameClientNum( i );
		s = NET_AdrToString( cl->netchan.remoteAddress );

		if (!avoidTruncation)
		{
			Com_Printf ("%2i %5i %s %-15.15s ^7%39s %5i\n",
				i,
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				s,
				cl->rate
				);
		}
		else
		{
			Com_Printf ("%2i %5i %s %s ^7%39s %5i\n",
				i,
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				s,
				cl->rate
				);
		}
	}
	Com_Printf ("\n");
}
示例#21
0
void SV_LinkEntity( sharedEntity_t *gEnt ) {
	worldSector_t	*node;
	int			leafs[MAX_TOTAL_ENT_LEAFS];
	int			cluster;
	int			num_leafs;
	int			i;
	int			area;
	int			lastLeaf;
	float		*origin, *angles;
	svEntity_t	*ent;
	sharedPlayerState_t	*ps;

	ent = SV_SvEntityForGentity( gEnt );

	if ( ent->worldSector ) {
		SV_UnlinkEntity( gEnt );	// unlink from old position
	}

	// get the position
	origin = gEnt->r.currentOrigin;
	angles = gEnt->r.currentAngles;

	// set the abs box
	if ( gEnt->s.bmodel && (angles[0] || angles[1] || angles[2]) ) {
		// expand for rotation
		float		max;

		max = RadiusFromBounds( gEnt->s.mins, gEnt->s.maxs );
		for (i=0 ; i<3 ; i++) {
			gEnt->r.absmin[i] = origin[i] - max;
			gEnt->r.absmax[i] = origin[i] + max;
		}
	} else {
		// normal
		VectorAdd (origin, gEnt->s.mins, gEnt->r.absmin);
		VectorAdd (origin, gEnt->s.maxs, gEnt->r.absmax);
	}

	// because movement is clipped an epsilon away from an actual edge,
	// we must fully check even when bounding boxes don't quite touch
	gEnt->r.absmin[0] -= 1;
	gEnt->r.absmin[1] -= 1;
	gEnt->r.absmin[2] -= 1;
	gEnt->r.absmax[0] += 1;
	gEnt->r.absmax[1] += 1;
	gEnt->r.absmax[2] += 1;

	// link to PVS leafs
	ent->numClusters = 0;
	ent->lastCluster = 0;
	ent->areanum = -1;
	ent->areanum2 = -1;

	//get all leafs, including solids
	num_leafs = CM_BoxLeafnums( gEnt->r.absmin, gEnt->r.absmax,
		leafs, MAX_TOTAL_ENT_LEAFS, &lastLeaf );

	// if none of the leafs were inside the map, the
	// entity is outside the world and can be considered unlinked
	if ( !num_leafs ) {
		return;
	}

	// set areas, even from clusters that don't fit in the entity array
	for (i=0 ; i<num_leafs ; i++) {
		area = CM_LeafArea (leafs[i]);
		if (area != -1) {
			// doors may legally straggle two areas,
			// but nothing should evern need more than that
			if (ent->areanum != -1 && ent->areanum != area) {
				if (ent->areanum2 != -1 && ent->areanum2 != area && sv.state == SS_LOADING) {
					Com_DPrintf ("Object %i touching 3 areas at %f %f %f\n",
					gEnt->s.number,
					gEnt->r.absmin[0], gEnt->r.absmin[1], gEnt->r.absmin[2]);
				}
				ent->areanum2 = area;
			} else {
				ent->areanum = area;
			}
		}
	}

	// store as many explicit clusters as we can
	ent->numClusters = 0;
	for (i=0 ; i < num_leafs ; i++) {
		cluster = CM_LeafCluster( leafs[i] );
		if ( cluster != -1 ) {
			ent->clusternums[ent->numClusters++] = cluster;
			if ( ent->numClusters == MAX_ENT_CLUSTERS ) {
				break;
			}
		}
	}

	// store off a last cluster if we need to
	if ( i != num_leafs ) {
		ent->lastCluster = CM_LeafCluster( lastLeaf );
	}

	gEnt->r.linkcount++;

	// find the first world sector node that the ent's box crosses
	node = sv_worldSectors;
	while (1)
	{
		if (node->axis == -1)
			break;
		if ( gEnt->r.absmin[node->axis] > node->dist)
			node = node->children[0];
		else if ( gEnt->r.absmax[node->axis] < node->dist)
			node = node->children[1];
		else
			break;		// crosses the node
	}
	
	// link it in
	ent->worldSector = node;
	ent->nextEntityInWorldSector = node->entities;
	node->entities = ent;

	gEnt->r.linked = qtrue;
	if (gEnt->s.number < MAX_CLIENTS) {
		ps = SV_GameClientNum(gEnt->s.number);
		ps->linked = qtrue;
	}
}
示例#22
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f(void)
{
	int           i, j, l;
	client_t      *cl;
	playerState_t *ps;
	const char    *s;
	int           ping;

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

	Com_Printf("cpu server utilization: %i %%\n"
	           "avg response time: %i ms\n"
	           "map: %s\n"
	           "num score ping name            lastmsg address               qport rate\n"
	           "--- ----- ---- --------------- ------- --------------------- ----- -----\n",
	           ( int ) svs.stats.cpu,
	           ( int ) svs.stats.avg,
	           sv_mapname->string);

	// FIXME: extend player name lenght (>16 chars) ? - they are printed!
	// FIXME: do a Com_Printf per line! ... create the row at first
	for (i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++)
	{
		if (!cl->state)
		{
			continue;
		}
		Com_Printf("%3i ", i);
		ps = SV_GameClientNum(i);
		Com_Printf("%5i ", ps->persistant[PERS_SCORE]);

		if (cl->state == CS_CONNECTED)
		{
			Com_Printf("CNCT ");
		}
		else if (cl->state == CS_ZOMBIE)
		{
			Com_Printf("ZMBI ");
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			Com_Printf("%4i ", ping);
		}

		Com_Printf("%s", rc(cl->name));
		l = 16 - strlen(cl->name);
		for (j = 0 ; j < l ; j++)
		{
			Com_Printf(" ");
		}

		Com_Printf("%7i ", svs.time - cl->lastPacketTime);

		s = NET_AdrToString(cl->netchan.remoteAddress);
		Com_Printf("%s", s);

		l = 22 - strlen(s);
		for (j = 0 ; j < l ; j++)
		{
			Com_Printf(" ");
		}

		Com_Printf("%5i", cl->netchan.qport);

		Com_Printf(" %5i\n", cl->rate);

	}
	Com_Printf("\n");
}
示例#23
0
/*
================
SV_Status_f
================
*/
static void SV_Status_f( void ) 
{
	int				i;
	client_t		*cl;
	playerState_t	*ps;
	const char		*s;
	int				ping;
	char			state[32];
	qboolean		avoidTruncation = qfalse;

	// make sure server is running
	if ( !com_sv_running->integer ) 
	{
		Com_Printf( SE_GetString("STR_SERVER_SERVER_NOT_RUNNING") );
		return;
	}

	if ( Cmd_Argc() > 1 )
	{
		if (!Q_stricmp("notrunc", Cmd_Argv(1)))
		{
			avoidTruncation = qtrue;
		}
	}

	Com_Printf ("map: %s\n", sv_mapname->string );

	Com_Printf ("num score ping name            lastmsg address               qport rate\n");
	Com_Printf ("--- ----- ---- --------------- ------- --------------------- ----- -----\n");
	for (i=0,cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++)
	{
		if (!cl->state)
		{
			continue;
		}

		if (cl->state == CS_CONNECTED)
		{
			strcpy(state, "CNCT ");
		}
		else if (cl->state == CS_ZOMBIE)
		{
			strcpy(state, "ZMBI ");
		}
		else
		{
			ping = cl->ping < 9999 ? cl->ping : 9999;
			sprintf(state, "%4i", ping);
		}

		ps = SV_GameClientNum( i );
		s = NET_AdrToString( cl->netchan.remoteAddress );

		if (!avoidTruncation)
		{
			Com_Printf ("%3i %5i %s %-15.15s %7i %21s %5i %5i\n", 
				i, 
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				svs.time - cl->lastPacketTime,
				s,
				cl->netchan.qport,
				cl->rate
				);
		}
		else
		{
			Com_Printf ("%3i %5i %s %s %7i %21s %5i %5i\n", 
				i, 
				ps->persistant[PERS_SCORE],
				state,
				cl->name,
				svs.time - cl->lastPacketTime,
				s,
				cl->netchan.qport,
				cl->rate
				);
		}
	}
	Com_Printf ("\n");
}