summaryrefslogtreecommitdiff
path: root/src/game/g_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/g_utils.c')
-rw-r--r--src/game/g_utils.c230
1 files changed, 225 insertions, 5 deletions
diff --git a/src/game/g_utils.c b/src/game/g_utils.c
index 95e117d2..b09ec8cb 100644
--- a/src/game/g_utils.c
+++ b/src/game/g_utils.c
@@ -155,7 +155,7 @@ void G_TeamCommand( pTeam_t team, char *cmd )
if( level.clients[ i ].pers.connected == CON_CONNECTED )
{
if( level.clients[ i ].ps.stats[ STAT_PTEAM ] == team )
- trap_SendServerCommand( i, va( "%s", cmd ) );
+ G_SendCommandFromServer( i, va( "%s", cmd ) );
}
}
}
@@ -683,6 +683,195 @@ void G_Sound( gentity_t *ent, int channel, int soundIndex )
}
+#define MAX_QUEUE_ELEMENTS MAX_CLIENTS * MAX_QUEUE_COMMANDS
+
+static commandQueueElement_t queuedCommandElements[ MAX_QUEUE_ELEMENTS ];
+static commandQueue_t queuedCommands[ MAX_CLIENTS ];
+
+/*
+===============
+G_PopCommandQueue
+
+Return the front of a command queue
+Must use immediately or copy to a buffer
+===============
+*/
+static const char *G_PopCommandQueue( commandQueue_t *cq )
+{
+ if( cq->front )
+ {
+ commandQueueElement_t *cqe = cq->front;
+
+ cq->front = cqe->next;
+
+ // last element in the queue
+ if( cq->front == NULL )
+ cq->back = NULL;
+
+ cq->nextCommandTime = level.time + g_minCommandPeriod.integer;
+ cqe->used = qfalse;
+
+ return cqe->command;
+ }
+ else
+ return NULL;
+}
+
+/*
+===============
+G_PushCommandQueue
+
+Put a command on a command queue
+===============
+*/
+static void G_PushCommandQueue( commandQueue_t *cq, const char *cmd )
+{
+ int i;
+
+ for( i = 0; i < MAX_QUEUE_ELEMENTS; i++ )
+ {
+ commandQueueElement_t *cqe = &queuedCommandElements[ i ];
+
+ if( !cqe->used )
+ {
+ cqe->used = qtrue;
+ cqe->next = NULL;
+ Q_strncpyz( cqe->command, cmd, MAX_TOKEN_CHARS );
+
+ if( cq->back )
+ {
+ cq->back->next = cqe;
+ cq->back = cqe;
+ }
+ else
+ {
+ cq->front = cqe;
+ cq->back = cqe;
+ }
+
+ return;
+ }
+ }
+
+ //drop the command
+}
+
+/*
+===============
+G_PrintCommandQueue
+===============
+*/
+#if 0 //quiet compiler
+static void G_PrintCommandQueue( commandQueue_t *cq )
+{
+ commandQueueElement_t *cqe;
+
+ if( cq->front )
+ {
+ cqe = cq->front;
+
+ do
+ {
+ G_Printf( "->\"%s\"", cqe->command );
+ } while( ( cqe = cqe->next ) );
+
+ G_Printf( "\n" );
+ }
+}
+#endif
+
+/*
+===============
+G_ReadyToDequeue
+===============
+*/
+static qboolean G_ReadyToDequeue( commandQueue_t *cq )
+{
+ if( !cq )
+ return qfalse;
+
+ return cq->front && cq->nextCommandTime <= level.time;
+}
+
+/*
+===============
+G_ProcessCommandQueues
+
+Check for any outstanding commands to be sent
+===============
+*/
+void G_ProcessCommandQueues( void )
+{
+ int i;
+
+ for( i = 0; i < MAX_CLIENTS; i++ )
+ {
+ commandQueue_t *cq = &queuedCommands[ i ];
+
+ if( G_ReadyToDequeue( cq ) )
+ {
+ const char *command = G_PopCommandQueue( cq );
+
+ if( command )
+ trap_SendServerCommand( i, command );
+ }
+ }
+}
+
+/*
+===============
+G_InitCommandQueue
+===============
+*/
+void G_InitCommandQueue( int clientNum )
+{
+ commandQueue_t *cq = &queuedCommands[ clientNum ];
+
+ if( clientNum >= 0 && clientNum < MAX_CLIENTS )
+ {
+ cq->front = cq->back = NULL;
+ cq->nextCommandTime = 0;
+ }
+}
+
+/*
+===============
+G_SendCommandFromServer
+
+Sends a command to a client
+===============
+*/
+void G_SendCommandFromServer( int clientNum, const char *cmd )
+{
+ commandQueue_t *cq = &queuedCommands[ clientNum ];
+
+ if( clientNum < 0 )
+ cq = NULL;
+
+ if( strlen( cmd ) > 1022 )
+ {
+ G_LogPrintf( "G_SendCommandFromServer( %d, ... ) length exceeds 1022.\n", clientNum );
+ G_LogPrintf( "cmd [%s]\n", cmd );
+ return;
+ }
+
+ if( cq )
+ {
+ if( cq->nextCommandTime > level.time )
+ {
+ //can't send yet, so queue the command up
+ G_PushCommandQueue( cq, cmd );
+ }
+ else
+ {
+ cq->nextCommandTime = level.time + g_minCommandPeriod.integer;
+ trap_SendServerCommand( clientNum, cmd );
+ }
+ }
+ else
+ trap_SendServerCommand( clientNum, cmd );
+}
+
//==============================================================================
@@ -735,8 +924,13 @@ gentity_t *G_FindRadius( gentity_t *from, vec3_t org, float rad )
return NULL;
}
-// (NOBODY): Code helper function
-//
+/*
+===============
+G_Visible
+
+Test for a LOS between two entities
+===============
+*/
qboolean G_Visible( gentity_t *ent1, gentity_t *ent2 )
{
trace_t trace;
@@ -749,6 +943,32 @@ qboolean G_Visible( gentity_t *ent1, gentity_t *ent2 )
return qtrue;
}
+/*
+===============
+G_ClosestEnt
+
+Test a list of entities for the closest to a particular point
+===============
+*/
+gentity_t *G_ClosestEnt( vec3_t origin, gentity_t **entities, int numEntities )
+{
+ int i;
+ float nd, d = 1000000.0f;
+ gentity_t *closestEnt = NULL;
+
+ for( i = 0; i < numEntities; i++ )
+ {
+ gentity_t *ent = entities[ i ];
+
+ if( ( nd = VectorDistance( origin, ent->s.origin ) ) < d )
+ {
+ d = nd;
+ closestEnt = ent;
+ }
+ }
+
+ return closestEnt;
+}
/*
===============
@@ -762,7 +982,7 @@ void G_TriggerMenu( int clientNum, dynMenu_t menu )
char buffer[ 32 ];
Com_sprintf( buffer, 32, "servermenu %d", menu );
- trap_SendServerCommand( clientNum, buffer );
+ G_SendCommandFromServer( clientNum, buffer );
}
@@ -778,7 +998,7 @@ void G_CloseMenus( int clientNum )
char buffer[ 32 ];
Com_sprintf( buffer, 32, "serverclosemenus" );
- trap_SendServerCommand( clientNum, buffer );
+ G_SendCommandFromServer( clientNum, buffer );
}