Example #1
0
void G_namelog_connect( gclient_t *client )
{
  namelog_t *n, *p = NULL;
  int       i;

  for( n = level.namelogs; n; p = n, n = n->next )
  {
    if( n->slot != -1 )
      continue;
    if( !Q_stricmp( client->pers.guid, n->guid ) )
      break;
  }
  if( !n )
  {
    n = BG_Alloc( sizeof( namelog_t ) );
    strcpy( n->guid, client->pers.guid );
    if( p )
      p->next = n;
    else
      level.namelogs = n;
  }
  client->pers.namelog = n;
  n->slot = client - level.clients;
  n->banned = qfalse;

  G_namelog_update_name( client );

  for( i = 0; i < MAX_NAMELOG_ADDRS && n->ip[ i ].str[ 0 ]; i++ )
    if( !strcmp( n->ip[ i ].str, client->pers.ip.str ) )
      return;
  if( i == MAX_NAMELOG_ADDRS )
    i--;
  memcpy( &n->ip[ i ], &client->pers.ip, sizeof( n->ip[ i ] ) );
}
Example #2
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.
============
*/
char *ClientUserinfoChanged( int clientNum, qboolean forceName )
{
    gentity_t *ent;
    char      *s;
    char      model[ MAX_QPATH ];
    char      buffer[ MAX_QPATH ];
    char      filename[ MAX_QPATH ];
    char      oldname[ MAX_NAME_LENGTH ];
    char      newname[ MAX_NAME_LENGTH ];
    char      err[ MAX_STRING_CHARS ];
    qboolean  revertName = qfalse;
    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\n\"" );
        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 ) );

    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 \"Name change spam protection (g_minNameChangePeriod = %d)\n\"",
                                        g_minNameChangePeriod.integer ) );
            revertName = qtrue;
        }
        else if( !forceName && g_maxNameChanges.integer > 0 &&
                 client->pers.namelog->nameChanges >= g_maxNameChanges.integer  )
        {
            trap_SendServerCommand( ent - g_entities, va(
                                        "print \"Maximum name changes reached (g_maxNameChanges = %d)\n\"",
                                        g_maxNameChanges.integer ) );
            revertName = qtrue;
        }
        else if( !forceName && client->pers.namelog->muted )
        {
            trap_SendServerCommand( ent - g_entities,
                                    "print \"You cannot change your name while you are muted\n\"" );
            revertName = qtrue;
        }
        else if( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
        {
            trap_SendServerCommand( ent - g_entities, va( "print \"%s\n\"", err ) );
            revertName = qtrue;
        }

        if( revertName )
        {
            Q_strncpyz( client->pers.netname, *oldname ? oldname : "UnnamedPlayer",
                        sizeof( client->pers.netname ) );
            Info_SetValueForKey( userinfo, "name", oldname );
            trap_SetUserinfo( clientNum, userinfo );
        }
        else
        {
            G_CensorString( client->pers.netname, newname,
                            sizeof( client->pers.netname ), ent );
            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\" \"%c%s%c^7\"\n",
                             clientNum, client->pers.ip.str, client->pers.guid,
                             oldname, client->pers.netname,
                             DECOLOR_OFF, client->pers.netname, DECOLOR_ON );
            }
        }
        G_namelog_update_name( client );
    }

    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_ClassConfig( PCL_HUMAN_BSUIT )->modelName,
                     BG_ClassConfig( PCL_HUMAN_BSUIT )->skinName );
    }
    else
    {
        Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( client->pers.classSelection )->modelName,
                     BG_ClassConfig( client->pers.classSelection )->skinName );

        //model segmentation
        Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg",
                     BG_ClassConfig( client->pers.classSelection )->modelName );

        if( G_NonSegModel( filename ) )
            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 = qtrue;
    else
        client->pers.disableBlueprintErrors = qfalse;

    // 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 = qtrue;
    else
        client->pers.useUnlagged = qfalse;

    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.teamSelection, model,
                 Com_ClientListString( &client->sess.ignoreList ),
                 client->pers.voice );

    trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

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

    return NULL;
}