summaryrefslogtreecommitdiff
path: root/source/sv_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/sv_send.c')
-rw-r--r--source/sv_send.c332
1 files changed, 176 insertions, 156 deletions
diff --git a/source/sv_send.c b/source/sv_send.c
index 680369f..e43db67 100644
--- a/source/sv_send.c
+++ b/source/sv_send.c
@@ -343,18 +343,18 @@ static inline void SV_PacketizedRemove( client_t *client, message_packet_t *msg
}
}
+#define FOR_EACH_MSG_SAFE( list ) LIST_FOR_EACH_SAFE( message_packet_t, msg, next, list, entry )
+
void SV_PacketizedClear( client_t *client ) {
message_packet_t *msg, *next;
- LIST_FOR_EACH_SAFE( message_packet_t, msg, next, &client->msg_used[0], entry ) {
- SV_PacketizedRemove( client, msg );
- }
- LIST_FOR_EACH_SAFE( message_packet_t, msg, next, &client->msg_used[1], entry ) {
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
SV_PacketizedRemove( client, msg );
}
- LIST_FOR_EACH_SAFE( message_packet_t, msg, next, &client->msg_sound, entry ) {
+ FOR_EACH_MSG_SAFE( &client->msg_used[1] ) {
SV_PacketizedRemove( client, msg );
}
+ client->msg_bytes = 0;
}
message_packet_t *SV_PacketizedAdd( client_t *client, byte *data,
@@ -384,12 +384,14 @@ message_packet_t *SV_PacketizedAdd( client_t *client, byte *data,
msg->cursize = ( uint16_t )len;
List_Append( &client->msg_used[reliable], &msg->entry );
+ if( !reliable ) {
+ client->msg_bytes += len;
+ }
return msg;
}
-static void SV_AddClientSounds( client_t *client, size_t maxsize ) {
- sound_packet_t *msg, *next;
+static void emit_snd( client_t *client, message_packet_t *msg ) {
edict_t *edict;
entity_state_t *state;
vec3_t origin;
@@ -397,75 +399,93 @@ static void SV_AddClientSounds( client_t *client, size_t maxsize ) {
int flags, entnum;
int i, j;
- frame = &client->frames[sv.framenum & UPDATE_MASK];
+ entnum = msg->sendchan >> 3;
+ flags = msg->flags;
- LIST_FOR_EACH_SAFE( sound_packet_t, msg, next, &client->msg_sound, entry ) {
- entnum = msg->sendchan >> 3;
- flags = msg->flags;
+ edict = EDICT_POOL( client, entnum );
+
+ // send origin for invisible entities
+ if( edict->svflags & SVF_NOCLIENT ) {
+ flags |= SND_POS;
+ }
- edict = EDICT_POOL( client, entnum );
-
- // send origin for invisible entities
- if( edict->svflags & SVF_NOCLIENT ) {
- flags |= SND_POS;
- }
+ // default client doesn't know that bmodels have weird origins
+ if( edict->solid == SOLID_BSP && client->protocol == PROTOCOL_VERSION_DEFAULT ) {
+ flags |= SND_POS;
+ }
- // default client doesn't know that bmodels have weird origins
- if( edict->solid == SOLID_BSP && client->protocol == PROTOCOL_VERSION_DEFAULT ) {
- flags |= SND_POS;
- }
+ // check if position needs to be explicitly sent
+ if( ( flags & SND_POS ) == 0 ) {
+ frame = &client->frames[sv.framenum & UPDATE_MASK];
- // check if position needs to be explicitly sent
- if( ( flags & SND_POS ) == 0 ) {
- for( i = 0; i < frame->numEntities; i++ ) {
- j = ( frame->firstEntity + i ) % svs.numEntityStates;
- state = &svs.entityStates[j];
- if( state->number == entnum ) {
- break;
- }
+ for( i = 0; i < frame->numEntities; i++ ) {
+ j = ( frame->firstEntity + i ) % svs.numEntityStates;
+ state = &svs.entityStates[j];
+ if( state->number == entnum ) {
+ break;
}
- if( i == frame->numEntities ) {
- if( sv_debug_send->integer ) {
- Com_Printf( S_COLOR_BLUE "Forcing position on entity %d for %s\n",
- entnum, client->name );
- }
- flags |= SND_POS; // entity is not present in frame
+ }
+ if( i == frame->numEntities ) {
+ if( sv_debug_send->integer ) {
+ Com_Printf( S_COLOR_BLUE "Forcing position on entity %d for %s\n",
+ entnum, client->name );
}
+ flags |= SND_POS; // entity is not present in frame
}
+ }
+
+ MSG_WriteByte( svc_sound );
+ MSG_WriteByte( flags );
+ MSG_WriteByte( msg->index );
- // if this msg fits, write it
- if( msg_write.cursize + 16 > maxsize ) {
- break;
+ if( flags & SND_VOLUME )
+ MSG_WriteByte( msg->volume );
+ if( flags & SND_ATTENUATION )
+ MSG_WriteByte( msg->attenuation );
+ if( flags & SND_OFFSET )
+ MSG_WriteByte( msg->timeofs );
+
+ MSG_WriteShort( msg->sendchan );
+
+ if( flags & SND_POS ) {
+ // use the entity origin unless it is a bmodel
+ if( edict->solid == SOLID_BSP ) {
+ VectorAvg( edict->mins, edict->maxs, origin );
+ VectorAdd( edict->s.origin, origin, origin );
+ } else {
+ VectorCopy( edict->s.origin, origin );
}
- MSG_WriteByte( svc_sound );
- MSG_WriteByte( flags );
- MSG_WriteByte( msg->index );
+ MSG_WritePos( origin );
+ }
+}
- if( flags & SND_VOLUME )
- MSG_WriteByte( msg->volume );
- if( flags & SND_ATTENUATION )
- MSG_WriteByte( msg->attenuation );
- if( flags & SND_OFFSET )
- MSG_WriteByte( msg->timeofs );
+static inline void write_snd( client_t *client, message_packet_t *msg, size_t maxsize ) {
+ // if this msg fits, write it
+ if( msg_write.cursize + MAX_SOUND_PACKET <= maxsize ) {
+ emit_snd( client, msg );
+ }
+ List_Remove( &msg->entry );
+ List_Insert( &client->msg_free, &msg->entry );
+}
- MSG_WriteShort( msg->sendchan );
+static inline void write_msg( client_t *client, message_packet_t *msg, size_t maxsize ) {
+ // if this msg fits, write it
+ if( msg_write.cursize + msg->cursize <= maxsize ) {
+ MSG_WriteData( msg->data, msg->cursize );
+ }
+ SV_PacketizedRemove( client, msg );
+}
- if( flags & SND_POS ) {
- // use the entity origin unless it is a bmodel
- if( edict->solid == SOLID_BSP ) {
- VectorAvg( edict->mins, edict->maxs, origin );
- VectorAdd( edict->s.origin, origin, origin );
- } else {
- VectorCopy( edict->s.origin, origin );
- }
+static inline void emit_messages( client_t *client, size_t maxsize ) {
+ message_packet_t *msg, *next;
- MSG_WritePos( origin );
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ if( msg->cursize ) {
+ write_msg( client, msg, maxsize );
+ } else {
+ write_snd( client, msg, maxsize );
}
-
- // move message to the free pool
- List_Remove( &msg->entry );
- List_Insert( &client->msg_free, &msg->entry );
}
}
@@ -477,9 +497,8 @@ FRAME UPDATES - DEFAULT, R1Q2 AND Q2PRO CLIENTS (OLD NETCHAN)
===============================================================================
*/
-#define FOR_EACH_MSG( list ) LIST_FOR_EACH_SAFE( message_packet_t, msg, next, list, entry )
-void SV_OldClientAddMessage( client_t *client, byte *data,
+void SV_ClientAddMessage_Old( client_t *client, byte *data,
size_t len, qboolean reliable )
{
if( len > client->netchan->maxpacketlen ) {
@@ -496,13 +515,13 @@ void SV_OldClientAddMessage( client_t *client, byte *data,
/*
=======================
-SV_OldClient_SendReliableMessages
+SV_ClientWriteReliableMessages_Old
This should be the only place data is
ever written to client->netchan.message
=======================
*/
-void SV_OldClientWriteReliableMessages( client_t *client, size_t maxsize ) {
+void SV_ClientWriteReliableMessages_Old( client_t *client, size_t maxsize ) {
message_packet_t *msg, *next;
int count;
@@ -515,7 +534,7 @@ void SV_OldClientWriteReliableMessages( client_t *client, size_t maxsize ) {
// find at least one reliable message to send
count = 0;
- FOR_EACH_MSG( &client->msg_used[1] ) {
+ FOR_EACH_MSG_SAFE( &client->msg_used[1] ) {
// stop if this msg doesn't fit (reliables must be delivered in order)
if( client->netchan->message.cursize + msg->cursize > maxsize ) {
if( !count ) {
@@ -536,22 +555,69 @@ void SV_OldClientWriteReliableMessages( client_t *client, size_t maxsize ) {
}
}
-static inline void write_msg( client_t *client, message_packet_t *msg, size_t maxsize ) {
- // if this msg fits, write it
- if( msg_write.cursize + msg->cursize <= maxsize ) {
- MSG_WriteData( msg->data, msg->cursize );
+static void repack_messages( client_t *client, size_t maxsize ) {
+ message_packet_t *msg, *next;
+
+ if( msg_write.cursize + 4 > maxsize ) {
+ return;
+ }
+
+ // temp entities first
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ if( !msg->cursize || msg->data[0] != svc_temp_entity ) {
+ continue;
+ }
+ // ignore some low-priority effects, these checks come from r1q2
+ if( msg->data[1] == TE_BLOOD || msg->data[1] == TE_SPLASH ||
+ msg->data[1] == TE_GUNSHOT || msg->data[1] == TE_BULLET_SPARKS ||
+ msg->data[1] == TE_SHOTGUN )
+ {
+ continue;
+ }
+ write_msg( client, msg, maxsize );
+ }
+
+ if( msg_write.cursize + 4 > maxsize ) {
+ return;
+ }
+
+ // then entity sounds
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ if( !msg->cursize ) {
+ write_snd( client, msg, maxsize );
+ }
+ }
+
+ if( msg_write.cursize + 4 > maxsize ) {
+ return;
+ }
+
+ // then positioned sounds
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ if( msg->cursize && msg->data[0] == svc_sound ) {
+ write_msg( client, msg, maxsize );
+ }
}
- SV_PacketizedRemove( client, msg );
-}
+ if( msg_write.cursize + 4 > maxsize ) {
+ return;
+ }
+
+ // then everything else left
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ if( msg->cursize ) {
+ write_msg( client, msg, maxsize );
+ }
+ }
+}
/*
=======================
-OldClient_SendDatagram
+SV_ClientWriteDatagram_Old
=======================
*/
-void SV_OldClientWriteDatagram( client_t *client ) {
- message_packet_t *msg, *next;
+void SV_ClientWriteDatagram_Old( client_t *client ) {
+ message_packet_t *msg;
size_t maxsize, cursize;
maxsize = client->netchan->maxpacketlen;
@@ -578,50 +644,19 @@ void SV_OldClientWriteDatagram( client_t *client ) {
SZ_Clear( &msg_write );
}
- // now try to write unreliable messages
- // it is necessary for this to be after the WriteEntities
+ // now write unreliable messages
+ // it is necessary for this to be after the WriteFrame
// so that entity references will be current
- if( msg_write.cursize + 4 <= maxsize ) {
- // temp entities first
- FOR_EACH_MSG( &client->msg_used[0] ) {
- if( msg->data[0] != svc_temp_entity ) {
- continue;
- }
- // ignore some low-priority effects, these checks come from r1q2
- if( msg->data[1] == TE_BLOOD || msg->data[1] == TE_SPLASH ||
- msg->data[1] == TE_GUNSHOT || msg->data[1] == TE_BULLET_SPARKS ||
- msg->data[1] == TE_SHOTGUN )
- {
- continue;
- }
- write_msg( client, msg, maxsize );
- }
-
- if( msg_write.cursize + 4 <= maxsize ) {
- // then entity sounds
- SV_AddClientSounds( client, maxsize );
-
- // then positioned sounds
- if( msg_write.cursize + 4 <= maxsize ) {
- FOR_EACH_MSG( &client->msg_used[0] ) {
- if( msg->data[0] != svc_sound ) {
- continue;
- }
- write_msg( client, msg, maxsize );
- }
+ if( msg_write.cursize + client->msg_bytes > maxsize ) {
+ // throw out some low priority effects
+ repack_messages( client, maxsize );
+ } else {
+ // all messages fit, write them in order
+ emit_messages( client, maxsize );
+ }
- if( msg_write.cursize + 4 <= maxsize ) {
- // then everything else left
- FOR_EACH_MSG( &client->msg_used[0] ) {
- write_msg( client, msg, maxsize );
- }
- }
- }
- }
- }
-
// write at least one reliable message
- SV_OldClientWriteReliableMessages( client,
+ SV_ClientWriteReliableMessages_Old( client,
client->netchan->maxpacketlen - msg_write.cursize );
// send the datagram
@@ -634,19 +669,6 @@ void SV_OldClientWriteDatagram( client_t *client ) {
SZ_Clear( &msg_write );
}
-void SV_OldClientFinishFrame( client_t *client ) {
- message_packet_t *msg, *next;
-
- // clear all unreliable messages still left
- FOR_EACH_MSG( &client->msg_used[0] ) {
- SV_PacketizedRemove( client, msg );
- }
-
- FOR_EACH_MSG( &client->msg_sound ) {
- SV_PacketizedRemove( client, msg );
- }
-}
-
/*
===============================================================================
@@ -655,14 +677,17 @@ FRAME UPDATES - Q2PRO CLIENTS (NEW NETCHAN)
===============================================================================
*/
-void SV_NewClientAddMessage( client_t *client, byte *data,
- size_t length, qboolean reliable )
+void SV_ClientAddMessage_New( client_t *client, byte *data,
+ size_t len, qboolean reliable )
{
- sizebuf_t *buf = reliable ? &client->netchan->message : &client->datagram;
- SZ_Write( buf, data, length );
+ if( reliable ) {
+ SZ_Write( &client->netchan->message, data, len );
+ } else {
+ SV_PacketizedAdd( client, data, len, qfalse );
+ }
}
-void SV_NewClientWriteDatagram( client_t *client ) {
+void SV_ClientWriteDatagram_New( client_t *client ) {
size_t cursize;
// send over all the relevant entity_state_t
@@ -675,19 +700,15 @@ void SV_NewClientWriteDatagram( client_t *client ) {
SZ_Clear( &msg_write );
}
- // copy the accumulated multicast datagram
+ // now write unreliable messages
// for this client out to the message
- // it is necessary for this to be after the WriteEntities
+ // it is necessary for this to be after the WriteFrame
// so that entity references will be current
- if( client->datagram.overflowed ) {
- Com_WPrintf( "Datagram overflowed for %s\n", client->name );
- } else if( msg_write.cursize + client->datagram.cursize > msg_write.maxsize ) {
+ if( msg_write.cursize + client->msg_bytes > msg_write.maxsize ) {
Com_WPrintf( "Dumping datagram for %s\n", client->name );
- } else {
- MSG_WriteData( client->datagram.data, client->datagram.cursize );
- }
-
- SV_AddClientSounds( client, msg_write.maxsize );
+ } else {
+ emit_messages( client, msg_write.maxsize );
+ }
if( sv_pad_packets->integer ) {
size_t pad = msg_write.cursize + sv_pad_packets->integer;
@@ -711,16 +732,6 @@ void SV_NewClientWriteDatagram( client_t *client ) {
SZ_Clear( &msg_write );
}
-void SV_NewClientFinishFrame( client_t *client ) {
- message_packet_t *msg, *next;
-
- // clear all unreliable messages still left
- SZ_Clear( &client->datagram );
-
- FOR_EACH_MSG( &client->msg_sound ) {
- SV_PacketizedRemove( client, msg );
- }
-}
/*
===============================================================================
@@ -730,6 +741,15 @@ COMMON STUFF
===============================================================================
*/
+static void finish_frame( client_t *client ) {
+ message_packet_t *msg, *next;
+
+ FOR_EACH_MSG_SAFE( &client->msg_used[0] ) {
+ SV_PacketizedRemove( client, msg );
+ }
+ client->msg_bytes = 0;
+}
+
/*
=======================
SV_SendClientMessages
@@ -774,8 +794,8 @@ void SV_SendClientMessages( void ) {
}
finish:
- // clear the unreliable datagram
- client->FinishFrame( client );
+ // clear all unreliable messages still left
+ finish_frame( client );
}
}