diff options
Diffstat (limited to 'src/game')
-rw-r--r-- | src/game/g_active.c | 2 | ||||
-rw-r--r-- | src/game/g_client.c | 3 | ||||
-rw-r--r-- | src/game/g_cmds.c | 99 | ||||
-rw-r--r-- | src/game/g_local.h | 58 | ||||
-rw-r--r-- | src/game/g_main.c | 2 |
5 files changed, 147 insertions, 17 deletions
diff --git a/src/game/g_active.c b/src/game/g_active.c index 44014ab9..d8229500 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -969,6 +969,8 @@ void ClientThink_real( gentity_t *ent ) return; } + G_UpdatePTRConnection( client ); + // check for inactivity timer, but never drop the local client of a non-dedicated server if( !ClientInactivityTimer( client ) ) return; diff --git a/src/game/g_client.c b/src/game/g_client.c index 441b2266..cbeafcb6 100644 --- a/src/game/g_client.c +++ b/src/game/g_client.c @@ -1196,6 +1196,9 @@ void ClientBegin( int clientNum ) } trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " entered the game\n\"", client->pers.netname ) ); + + // request the clients PTR code + trap_SendServerCommand( ent - g_entities, "ptrcrequest" ); G_LogPrintf( "ClientBegin: %i\n", clientNum ); diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 3dd7c672..ac6e37e5 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -459,6 +459,8 @@ void G_ChangeTeam( gentity_t *ent, pTeam_t newTeam ) ClientSpawn( ent, NULL, NULL, NULL ); } + ent->client->pers.joinedATeam = qtrue; + //update ClientInfo ClientUserinfoChanged( ent->client->ps.clientNum ); } @@ -2118,6 +2120,99 @@ void Cmd_FollowCycle_f( gentity_t *ent, int dir ) // leave it where it was } +/* +================= +Cmd_PTRCVerify_f + +Check a PTR code is valid +================= +*/ +void Cmd_PTRCVerify_f( gentity_t *ent ) +{ + connectionRecord_t *connection; + char s[ MAX_TOKEN_CHARS ] = { 0 }; + int code; + + trap_Argv( 1, s, sizeof( s ) ); + + if( !strlen( s ) ) + return; + + code = atoi( s ); + + if( G_VerifyPTRC( code ) ) + { + connection = G_FindConnectionForCode( code ); + + // valid code + if( connection->clientTeam != PTE_NONE ) + trap_SendServerCommand( ent->client->ps.clientNum, "ptrcconfirm" ); + + // restore mapping + ent->client->pers.connection = connection; + } + else + { + // invalid code -- generate a new one + connection = G_GenerateNewConnection( ent->client ); + + if( connection ) + { + trap_SendServerCommand( ent->client->ps.clientNum, + va( "ptrcissue %d", connection->ptrCode ) ); + } + } +} + +/* +================= +Cmd_PTRCRestore_f + +Restore against a PTR code +================= +*/ +void Cmd_PTRCRestore_f( gentity_t *ent ) +{ + char s[ MAX_TOKEN_CHARS ] = { 0 }; + int code; + connectionRecord_t *connection; + + trap_Argv( 1, s, sizeof( s ) ); + + if( !strlen( s ) ) + return; + + code = atoi( s ); + + if( G_VerifyPTRC( code ) ) + { + if( ent->client->pers.joinedATeam ) + { + trap_SendServerCommand( ent - g_entities, + "print \"You cannot use a PTR code after joining a team\n\"" ); + } + else + { + // valid code + connection = G_FindConnectionForCode( code ); + + if( connection ) + { + // set the correct team + G_ChangeTeam( ent, connection->clientTeam ); + + // set the correct credit + ent->client->ps.persistant[ PERS_CREDIT ] = 0; + G_AddCreditToClient( ent->client, connection->clientCredit ); + } + } + } + else + { + trap_SendServerCommand( ent - g_entities, + va( "print \"\"%d\" is not a valid PTR code\n\"", code ) ); + } +} /* ================= @@ -2327,6 +2422,10 @@ void ClientCommand( int clientNum ) Cmd_TeamVote_f( ent ); else if( Q_stricmp( cmd, "setviewpos" ) == 0 ) Cmd_SetViewpos_f( ent ); + else if( Q_stricmp( cmd, "ptrcverify" ) == 0 ) + Cmd_PTRCVerify_f( ent ); + else if( Q_stricmp( cmd, "ptrcrestore" ) == 0 ) + Cmd_PTRCRestore_f( ent ); else if( Q_stricmp( cmd, "test" ) == 0 ) Cmd_Test_f( ent ); else if( Q_stricmp( cmd, "evolvebug" ) == 0 ) diff --git a/src/game/g_local.h b/src/game/g_local.h index 6fe638e9..2885da8b 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -291,27 +291,40 @@ typedef struct #define MAX_NETNAME 36 #define MAX_VOTE_COUNT 3 +// data to store details of clients that have abnormally disconnected +typedef struct connectionRecord_s +{ + int clientNum; + pTeam_t clientTeam; + int clientCredit; + + int ptrCode; +} connectionRecord_t; + // client data that stays across multiple respawns, but is cleared // on each level change or team change at ClientBegin() typedef struct { - clientConnected_t connected; - usercmd_t cmd; // we would lose angles if not persistant - qboolean localClient; // true if "ip" info key is "localhost" - qboolean initialSpawn; // the first spawn should be at a cool location - qboolean predictItemPickup; // based on cg_predictItems userinfo - qboolean pmoveFixed; // - char netname[ MAX_NETNAME ]; - int maxHealth; // for handicapping - int enterTime; // level.time the client entered the game - playerTeamState_t teamState; // status in teamplay games - int voteCount; // to prevent people from constantly calling votes - int teamVoteCount; // to prevent people from constantly calling votes - qboolean teamInfo; // send team overlay updates? - - pClass_t classSelection; //TA: player class (copied to ent->client->ps.stats[ STAT_PCLASS ] once spawned) - weapon_t humanItemSelection; //TA: humans have a starting item - pTeam_t teamSelection; //TA: player team (copied to ps.stats[ STAT_PTEAM ]) + clientConnected_t connected; + usercmd_t cmd; // we would lose angles if not persistant + qboolean localClient; // true if "ip" info key is "localhost" + qboolean initialSpawn; // the first spawn should be at a cool location + qboolean predictItemPickup; // based on cg_predictItems userinfo + qboolean pmoveFixed; // + char netname[ MAX_NETNAME ]; + int maxHealth; // for handicapping + int enterTime; // level.time the client entered the game + playerTeamState_t teamState; // status in teamplay games + int voteCount; // to prevent people from constantly calling votes + int teamVoteCount; // to prevent people from constantly calling votes + qboolean teamInfo; // send team overlay updates? + + pClass_t classSelection; //TA: player class (copied to ent->client->ps.stats[ STAT_PCLASS ] once spawned) + weapon_t humanItemSelection; //TA: humans have a starting item + pTeam_t teamSelection; //TA: player team (copied to ps.stats[ STAT_PTEAM ]) + + qboolean joinedATeam; //TA: used to tell when a PTR code is valid + connectionRecord_t *connection; } clientPersistant_t; // this structure is cleared on each ClientSpawn(), @@ -916,6 +929,17 @@ void G_StopMapRotation( void ); qboolean G_MapRotationActive( void ); void G_InitMapRotations( void ); +// +// g_ptr.c +// +void G_UpdatePTRConnection( gclient_t *client ); +connectionRecord_t *G_GenerateNewConnection( gclient_t *client ); +qboolean G_VerifyPTRC( int code ); +void G_ResetPTRConnections( void ); +connectionRecord_t *G_FindConnectionForCode( int code ); +void G_DeletePTRConnection( connectionRecord_t *connection ); + + //some maxs #define MAX_FILEPATH 144 diff --git a/src/game/g_main.c b/src/game/g_main.c index 2a54b521..93a3c8a6 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -547,6 +547,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) //TA: so the server counts the spawns without a client attached G_CountSpawns( ); + + G_ResetPTRConnections( ); } |