示例#1
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
const char *ClientUserinfoChanged( int clientNum, bool forceName )
{
	gentity_t *ent;
	const char      *s;
	char      model[ MAX_QPATH ];
	char      buffer[ MAX_QPATH ];
	char      oldname[ MAX_NAME_LENGTH ];
	char      newname[ MAX_NAME_LENGTH ];
	char      err[ MAX_STRING_CHARS ];
	bool  revertName = false;
	gclient_t *client;
	char      userinfo[ MAX_INFO_STRING ];

	ent = g_entities + clientNum;
	client = ent->client;

	trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

	// check for malformed or illegal info strings
	if ( !Info_Validate( userinfo ) )
	{
		trap_SendServerCommand( ent - g_entities,
		                        "disconnect \"illegal or malformed userinfo\"" );
		trap_DropClient( ent - g_entities,
		                 "dropped: illegal or malformed userinfo" );
		return "Illegal or malformed userinfo";
	}
	// If their userinfo overflowed, tremded is in the process of disconnecting them.
	// If we send our own disconnect, it won't work, so just return to prevent crashes later
	//  in this function. This check must come after the Info_Validate call.
	else if ( !userinfo[ 0 ] )
	{
		return "Empty (overflowed) userinfo";
	}

	// stickyspec toggle
	s = Info_ValueForKey( userinfo, "cg_stickySpec" );
	client->pers.stickySpec = atoi( s ) != 0;

	// set name
	Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) );
	s = Info_ValueForKey( userinfo, "name" );
	G_ClientCleanName( s, newname, sizeof( newname ), client );

	if ( strcmp( oldname, newname ) )
	{
		if ( !forceName && client->pers.namelog->nameChangeTime &&
		     level.time - client->pers.namelog->nameChangeTime <=
		     g_minNameChangePeriod.value * 1000 )
		{
			trap_SendServerCommand( ent - g_entities, va(
			                          "print_tr %s %d", QQ( N_("Name change spam protection (g_minNameChangePeriod = $1$)") ),
			                          g_minNameChangePeriod.integer ) );
			revertName = true;
		}
		else if ( !forceName && g_maxNameChanges.integer > 0 &&
		          client->pers.namelog->nameChanges >= g_maxNameChanges.integer )
		{
			trap_SendServerCommand( ent - g_entities, va(
			                          "print_tr %s %d", QQ( N_("Maximum name changes reached (g_maxNameChanges = $1$)") ),
			                          g_maxNameChanges.integer ) );
			revertName = true;
		}
		else if ( !forceName && client->pers.namelog->muted )
		{
			trap_SendServerCommand( ent - g_entities,
			                        va( "print_tr %s", QQ( N_("You cannot change your name while you are muted") ) ) );
			revertName = true;
		}
		else if ( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
		{
			trap_SendServerCommand( ent - g_entities, va( "print_tr %s %s %s", QQ( "$1t$ $2$" ), Quote( err ), Quote( newname ) ) );
			revertName = true;
		}
		else if ( Q_UTF8_Strlen( newname ) > MAX_NAME_CHARACTERS )
		{
			trap_SendServerCommand( ent - g_entities,
			                        va( "print_tr %s %d", QQ( N_("Name is too long! Must be less than $1$ characters.") ), MAX_NAME_CHARACTERS ) );
			revertName = true;

		}

		if ( revertName )
		{
			Q_strncpyz( client->pers.netname, *oldname ? oldname : G_UnnamedClientName( client ),
			            sizeof( client->pers.netname ) );
		}
		else
		{
			if( G_IsUnnamed( newname ) )
			{
				Q_strncpyz( client->pers.netname, G_UnnamedClientName( client ), sizeof( client->pers.netname ) );
			}
			else
			{
				Q_strncpyz( client->pers.netname, newname, sizeof( client->pers.netname ) );
			}

			if ( !forceName && client->pers.connected == CON_CONNECTED )
			{
				client->pers.namelog->nameChangeTime = level.time;
				client->pers.namelog->nameChanges++;
			}

			if ( *oldname )
			{
				G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s^7\" -> \"%s^7\" \"%s^7\"",
				             clientNum, client->pers.ip.str, client->pers.guid,
				             oldname, client->pers.netname,
				             client->pers.netname );
			}
		}

		G_namelog_update_name( client );

		Info_SetValueForKey(userinfo, "name", client->pers.netname, false);
		trap_SetUserinfo(clientNum, userinfo);
	}

	if ( client->pers.classSelection == PCL_NONE )
	{
		//This looks hacky and frankly it is. The clientInfo string needs to hold different
		//model details to that of the spawning class or the info change will not be
		//registered and an axis appears instead of the player model. There is zero chance
		//the player can spawn with the battlesuit, hence this choice.
		Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassModelConfig( PCL_HUMAN_BSUIT )->modelName,
		             BG_ClassModelConfig( PCL_HUMAN_BSUIT )->skinName );
	}
	else
	{
		Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassModelConfig( client->pers.classSelection )->modelName,
		             BG_ClassModelConfig( client->pers.classSelection )->skinName );

		if ( BG_ClassModelConfig( client->pers.classSelection )->segmented )
		{
			client->ps.persistant[ PERS_STATE ] |= PS_NONSEGMODEL;
		}
		else
		{
			client->ps.persistant[ PERS_STATE ] &= ~PS_NONSEGMODEL;
		}
	}

	Q_strncpyz( model, buffer, sizeof( model ) );

	// wallwalk follow
	s = Info_ValueForKey( userinfo, "cg_wwFollow" );

	if ( atoi( s ) )
	{
		client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGFOLLOW;
	}
	else
	{
		client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGFOLLOW;
	}

	// wallwalk toggle
	s = Info_ValueForKey( userinfo, "cg_wwToggle" );

	if ( atoi( s ) )
	{
		client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGTOGGLE;
	}
	else
	{
		client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGTOGGLE;
	}

	// always sprint
	s = Info_ValueForKey( userinfo, "cg_sprintToggle" );

	if ( atoi( s ) )
	{
		client->ps.persistant[ PERS_STATE ] |= PS_SPRINTTOGGLE;
	}
	else
	{
		client->ps.persistant[ PERS_STATE ] &= ~PS_SPRINTTOGGLE;
	}

	// fly speed
	s = Info_ValueForKey( userinfo, "cg_flySpeed" );

	if ( *s )
	{
		client->pers.flySpeed = atoi( s );
	}
	else
	{
		client->pers.flySpeed = BG_Class( PCL_NONE )->speed;
	}

	// disable blueprint errors
	s = Info_ValueForKey( userinfo, "cg_disableBlueprintErrors" );

	if ( atoi( s ) )
	{
		client->pers.disableBlueprintErrors = true;
	}
	else
	{
		client->pers.disableBlueprintErrors = false;
	}

	// teamInfo
	s = Info_ValueForKey( userinfo, "teamoverlay" );

	if ( atoi( s ) != 0 )
	{
		// teamoverlay was enabled so we need an update
		if ( client->pers.teamInfo == 0 )
		{
			client->pers.teamInfo = 1;
		}
	}
	else
	{
		client->pers.teamInfo = 0;
	}

	s = Info_ValueForKey( userinfo, "cg_unlagged" );

	if ( !s[ 0 ] || atoi( s ) != 0 )
	{
		client->pers.useUnlagged = true;
	}
	else
	{
		client->pers.useUnlagged = false;
	}

	Q_strncpyz( client->pers.voice, Info_ValueForKey( userinfo, "voice" ),
	            sizeof( client->pers.voice ) );

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds

	Com_sprintf( userinfo, sizeof( userinfo ),
	             "n\\%s\\t\\%i\\model\\%s\\ig\\%16s\\v\\%s",
	             client->pers.netname, client->pers.team, model,
	             Com_ClientListString( &client->sess.ignoreList ),
	             client->pers.voice );

	trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

	/*G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, userinfo );*/

	return nullptr;
}
示例#2
0
/*
================
Con_CheckResize

If the line width has changed, reformat the buffer.
================
*/
qboolean Con_CheckResize( void )
{
	int   i, textWidthInChars, oldwidth, oldtotallines, numlines, numchars;
	conChar_t buf[ CON_TEXTSIZE ];
	qboolean  ret = qtrue;

	if ( cls.glconfig.vidWidth )
	{
		const int consoleVidWidth = cls.glconfig.vidWidth - 2 * (consoleState.margin.sides + consoleState.padding.sides );
		textWidthInChars = consoleVidWidth / SCR_ConsoleFontUnicharWidth( 'W' );
	}
	else
	{
		textWidthInChars = 0;
	}

	if ( textWidthInChars == consoleState.textWidthInChars )
	{
		// nothing
	}
	else if ( textWidthInChars < 1 ) // video hasn't been initialized yet
	{
		consoleState.textWidthInChars = DEFAULT_CONSOLE_WIDTH;
		consoleState.maxScrollbackLengthInLines = CON_TEXTSIZE / consoleState.textWidthInChars;
		Con_Clear();

		consoleState.currentLine = consoleState.maxScrollbackLengthInLines - 1;
		consoleState.bottomDisplayedLine = consoleState.currentLine;
		consoleState.scrollLineIndex = consoleState.currentLine;

		ret = qfalse;
	}
	else
	{
		oldwidth = consoleState.textWidthInChars;
		consoleState.textWidthInChars = textWidthInChars;
		oldtotallines = consoleState.maxScrollbackLengthInLines;
		consoleState.maxScrollbackLengthInLines = CON_TEXTSIZE / consoleState.textWidthInChars;
		numlines = oldwidth < 0 ? 0 : oldtotallines;

		if ( consoleState.maxScrollbackLengthInLines < numlines )
		{
			numlines = consoleState.maxScrollbackLengthInLines;
		}

		numchars = oldwidth;

		if ( consoleState.textWidthInChars < numchars )
		{
			numchars = consoleState.textWidthInChars;
		}

		Com_Memcpy( buf, consoleState.text, sizeof( consoleState.text ) );
		Con_Clear();

		for ( i = 0; i < numlines; i++ )
		{
			conChar_t* destination = consoleState.text + ( consoleState.maxScrollbackLengthInLines - 1 - i ) * consoleState.textWidthInChars;
			memcpy( destination,
			        buf + ( ( consoleState.currentLine - i + oldtotallines ) % oldtotallines ) * oldwidth,
			        numchars * sizeof( conChar_t ) );

			if( destination[0].ch )
				consoleState.usedScrollbackLengthInLines++;
		}

		consoleState.currentLine = consoleState.maxScrollbackLengthInLines - 1;
		consoleState.bottomDisplayedLine = consoleState.currentLine;
		consoleState.scrollLineIndex = consoleState.currentLine;
	}

	if ( con_prompt )
	{
		char prompt[ MAX_STRING_CHARS ];

		Q_strncpyz( prompt, con_prompt->string, sizeof( prompt ) );
		Q_CleanStr( prompt );

		g_console_field_width = consoleState.textWidthInChars - 8 - Q_UTF8_Strlen( prompt );
		g_consoleField.SetWidth(g_console_field_width);
	}

	return ret;
}