summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/g_active.c2
-rw-r--r--src/game/g_client.c3
-rw-r--r--src/game/g_cmds.c99
-rw-r--r--src/game/g_local.h58
-rw-r--r--src/game/g_main.c2
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( );
}