#include "server.h"
Include dependency graph for sv_snapshot.c:

Go to the source code of this file.
Data Structures | |
| struct | snapshotEntityNumbers_t |
Defines | |
| #define | HEADER_RATE_BYTES 48 |
| #define | MAX_SNAPSHOT_ENTITIES 1024 |
Functions | |
| void | SV_AddEntitiesVisibleFromPoint (vec3_t origin, clientSnapshot_t *frame, snapshotEntityNumbers_t *eNums, qboolean portal) |
| void | SV_AddEntToSnapshot (svEntity_t *svEnt, sharedEntity_t *gEnt, snapshotEntityNumbers_t *eNums) |
| void | SV_BuildClientSnapshot (client_t *client) |
| void | SV_EmitPacketEntities (clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg) |
| int QDECL | SV_QsortEntityNumbers (const void *a, const void *b) |
| int | SV_RateMsec (client_t *client, int messageSize) |
| void | SV_SendClientMessages (void) |
| void | SV_SendClientSnapshot (client_t *client) |
| void | SV_SendMessageToClient (msg_t *msg, client_t *client) |
| void | SV_UpdateServerCommandsToClient (client_t *client, msg_t *msg) |
| void | SV_WriteSnapshotToClient (client_t *client, msg_t *msg) |
|
|
Definition at line 526 of file sv_snapshot.c. |
|
|
Definition at line 228 of file sv_snapshot.c. |
|
||||||||||||||||||||
|
Definition at line 283 of file sv_snapshot.c. References clientSnapshot_t::areabits, clientSnapshot_t::areabytes, svEntity_s::areanum, svEntity_s::areanum2, byte, playerState_s::clientNum, svEntity_s::clusternums, CM_AreasConnected(), CM_ClusterPVS(), CM_LeafArea(), CM_LeafCluster(), CM_PointLeafnum(), CM_WriteAreaBits(), Com_DPrintf(), Com_Error(), e, ERR_DROP, entityState_s::generic1, i, l, svEntity_s::lastCluster, entityShared_t::linked, server_t::num_entities, entityState_s::number, svEntity_s::numClusters, entityState_s::origin, entityState_s::origin2, clientSnapshot_t::ps, qtrue, sharedEntity_t::r, sharedEntity_t::s, entityShared_t::singleClient, server_t::snapshotCounter, svEntity_s::snapshotCounter, server_t::state, sv, SV_AddEntToSnapshot(), SV_GentityNum(), SV_SvEntityForGentity(), svEntity_t, entityShared_t::svFlags, vec3_t, VectorLengthSquared(), and VectorSubtract. Referenced by SV_BuildClientSnapshot(). 00284 {
00285 int e, i;
00286 sharedEntity_t *ent;
00287 svEntity_t *svEnt;
00288 int l;
00289 int clientarea, clientcluster;
00290 int leafnum;
00291 int c_fullsend;
00292 byte *clientpvs;
00293 byte *bitvector;
00294
00295 // during an error shutdown message we may need to transmit
00296 // the shutdown message after the server has shutdown, so
00297 // specfically check for it
00298 if ( !sv.state ) {
00299 return;
00300 }
00301
00302 leafnum = CM_PointLeafnum (origin);
00303 clientarea = CM_LeafArea (leafnum);
00304 clientcluster = CM_LeafCluster (leafnum);
00305
00306 // calculate the visible areas
00307 frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );
00308
00309 clientpvs = CM_ClusterPVS (clientcluster);
00310
00311 c_fullsend = 0;
00312
00313 for ( e = 0 ; e < sv.num_entities ; e++ ) {
00314 ent = SV_GentityNum(e);
00315
00316 // never send entities that aren't linked in
00317 if ( !ent->r.linked ) {
00318 continue;
00319 }
00320
00321 if (ent->s.number != e) {
00322 Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
00323 ent->s.number = e;
00324 }
00325
00326 // entities can be flagged to explicitly not be sent to the client
00327 if ( ent->r.svFlags & SVF_NOCLIENT ) {
00328 continue;
00329 }
00330
00331 // entities can be flagged to be sent to only one client
00332 if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
00333 if ( ent->r.singleClient != frame->ps.clientNum ) {
00334 continue;
00335 }
00336 }
00337 // entities can be flagged to be sent to everyone but one client
00338 if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
00339 if ( ent->r.singleClient == frame->ps.clientNum ) {
00340 continue;
00341 }
00342 }
00343 // entities can be flagged to be sent to a given mask of clients
00344 if ( ent->r.svFlags & SVF_CLIENTMASK ) {
00345 if (frame->ps.clientNum >= 32)
00346 Com_Error( ERR_DROP, "SVF_CLIENTMASK: cientNum > 32\n" );
00347 if (~ent->r.singleClient & (1 << frame->ps.clientNum))
00348 continue;
00349 }
00350
00351 svEnt = SV_SvEntityForGentity( ent );
00352
00353 // don't double add an entity through portals
00354 if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
00355 continue;
00356 }
00357
00358 // broadcast entities are always sent
00359 if ( ent->r.svFlags & SVF_BROADCAST ) {
00360 SV_AddEntToSnapshot( svEnt, ent, eNums );
00361 continue;
00362 }
00363
00364 // ignore if not touching a PV leaf
00365 // check area
00366 if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
00367 // doors can legally straddle two areas, so
00368 // we may need to check another one
00369 if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
00370 continue; // blocked by a door
00371 }
00372 }
00373
00374 bitvector = clientpvs;
00375
00376 // check individual leafs
00377 if ( !svEnt->numClusters ) {
00378 continue;
00379 }
00380 l = 0;
00381 for ( i=0 ; i < svEnt->numClusters ; i++ ) {
00382 l = svEnt->clusternums[i];
00383 if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
00384 break;
00385 }
00386 }
00387
00388 // if we haven't found it to be visible,
00389 // check overflow clusters that coudln't be stored
00390 if ( i == svEnt->numClusters ) {
00391 if ( svEnt->lastCluster ) {
00392 for ( ; l <= svEnt->lastCluster ; l++ ) {
00393 if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
00394 break;
00395 }
00396 }
00397 if ( l == svEnt->lastCluster ) {
00398 continue; // not visible
00399 }
00400 } else {
00401 continue;
00402 }
00403 }
00404
00405 // add it
00406 SV_AddEntToSnapshot( svEnt, ent, eNums );
00407
00408 // if its a portal entity, add everything visible from its camera position
00409 if ( ent->r.svFlags & SVF_PORTAL ) {
00410 if ( ent->s.generic1 ) {
00411 vec3_t dir;
00412 VectorSubtract(ent->s.origin, origin, dir);
00413 if ( VectorLengthSquared(dir) > (float) ent->s.generic1 * ent->s.generic1 ) {
00414 continue;
00415 }
00416 }
00417 SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
00418 }
00419
00420 }
00421 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 262 of file sv_snapshot.c. References entityState_s::number, snapshotEntityNumbers_t::numSnapshotEntities, sharedEntity_t::s, server_t::snapshotCounter, svEntity_s::snapshotCounter, snapshotEntityNumbers_t::snapshotEntities, sv, and svEntity_t. Referenced by SV_AddEntitiesVisibleFromPoint(). 00262 {
00263 // if we have already added this entity to this snapshot, don't add again
00264 if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
00265 return;
00266 }
00267 svEnt->snapshotCounter = sv.snapshotCounter;
00268
00269 // if we are full, silently discard entities
00270 if ( eNums->numSnapshotEntities == MAX_SNAPSHOT_ENTITIES ) {
00271 return;
00272 }
00273
00274 eNums->snapshotEntities[ eNums->numSnapshotEntities ] = gEnt->s.number;
00275 eNums->numSnapshotEntities++;
00276 }
|
|
|
Definition at line 436 of file sv_snapshot.c. References clientSnapshot_t::areabits, client_t, playerState_s::clientNum, serverStatic_t::clients, Com_Error(), Com_Memset(), entityState_t, ERR_DROP, ERR_FATAL, clientSnapshot_t::first_entity, client_s::frames, client_s::gentity, i, MAX_MAP_AREA_BYTES, client_s::netchan, serverStatic_t::nextSnapshotEntities, clientSnapshot_t::num_entities, serverStatic_t::numSnapshotEntities, snapshotEntityNumbers_t::numSnapshotEntities, playerState_s::origin, netchan_t::outgoingSequence, playerState_t, clientSnapshot_t::ps, qfalse, qsort(), sharedEntity_t::s, svEntity_s::snapshotCounter, server_t::snapshotCounter, serverStatic_t::snapshotEntities, snapshotEntityNumbers_t::snapshotEntities, state, client_s::state, sv, SV_AddEntitiesVisibleFromPoint(), SV_GameClientNum(), SV_GentityNum(), SV_QsortEntityNumbers(), server_t::svEntities, svEntity_t, svs, vec3_t, VectorCopy, and playerState_s::viewheight. Referenced by SV_SendClientSnapshot(). 00436 {
00437 vec3_t org;
00438 clientSnapshot_t *frame;
00439 snapshotEntityNumbers_t entityNumbers;
00440 int i;
00441 sharedEntity_t *ent;
00442 entityState_t *state;
00443 svEntity_t *svEnt;
00444 sharedEntity_t *clent;
00445 int clientNum;
00446 playerState_t *ps;
00447
00448 // bump the counter used to prevent double adding
00449 sv.snapshotCounter++;
00450
00451 // this is the frame we are creating
00452 frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
00453
00454 // clear everything in this snapshot
00455 entityNumbers.numSnapshotEntities = 0;
00456 Com_Memset( frame->areabits, 0, sizeof( frame->areabits ) );
00457
00458 // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=62
00459 frame->num_entities = 0;
00460
00461 clent = client->gentity;
00462 if ( !clent || client->state == CS_ZOMBIE ) {
00463 return;
00464 }
00465
00466 // grab the current playerState_t
00467 ps = SV_GameClientNum( client - svs.clients );
00468 frame->ps = *ps;
00469
00470 // never send client's own entity, because it can
00471 // be regenerated from the playerstate
00472 clientNum = frame->ps.clientNum;
00473 if ( clientNum < 0 || clientNum >= MAX_GENTITIES ) {
00474 Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" );
00475 }
00476 svEnt = &sv.svEntities[ clientNum ];
00477
00478 svEnt->snapshotCounter = sv.snapshotCounter;
00479
00480 // find the client's viewpoint
00481 VectorCopy( ps->origin, org );
00482 org[2] += ps->viewheight;
00483
00484 // add all the entities directly visible to the eye, which
00485 // may include portal entities that merge other viewpoints
00486 SV_AddEntitiesVisibleFromPoint( org, frame, &entityNumbers, qfalse );
00487
00488 // if there were portals visible, there may be out of order entities
00489 // in the list which will need to be resorted for the delta compression
00490 // to work correctly. This also catches the error condition
00491 // of an entity being included twice.
00492 qsort( entityNumbers.snapshotEntities, entityNumbers.numSnapshotEntities,
00493 sizeof( entityNumbers.snapshotEntities[0] ), SV_QsortEntityNumbers );
00494
00495 // now that all viewpoint's areabits have been OR'd together, invert
00496 // all of them to make it a mask vector, which is what the renderer wants
00497 for ( i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++ ) {
00498 ((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
00499 }
00500
00501 // copy the entity states out
00502 frame->num_entities = 0;
00503 frame->first_entity = svs.nextSnapshotEntities;
00504 for ( i = 0 ; i < entityNumbers.numSnapshotEntities ; i++ ) {
00505 ent = SV_GentityNum(entityNumbers.snapshotEntities[i]);
00506 state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
00507 *state = ent->s;
00508 svs.nextSnapshotEntities++;
00509 // this should never hit, map should always be restarted first in SV_Frame
00510 if ( svs.nextSnapshotEntities >= 0x7FFFFFFE ) {
00511 Com_Error(ERR_FATAL, "svs.nextSnapshotEntities wrapped");
00512 }
00513 frame->num_entities++;
00514 }
00515 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 55 of file sv_snapshot.c. References svEntity_s::baseline, entityState_t, clientSnapshot_t::first_entity, GENTITYNUM_BITS, MAX_GENTITIES, MSG_WriteBits(), MSG_WriteDeltaEntity(), NULL, clientSnapshot_t::num_entities, entityState_s::number, serverStatic_t::numSnapshotEntities, qfalse, qtrue, serverStatic_t::snapshotEntities, sv, server_t::svEntities, and svs. Referenced by SV_WriteSnapshotToClient(). 00055 {
00056 entityState_t *oldent, *newent;
00057 int oldindex, newindex;
00058 int oldnum, newnum;
00059 int from_num_entities;
00060
00061 // generate the delta update
00062 if ( !from ) {
00063 from_num_entities = 0;
00064 } else {
00065 from_num_entities = from->num_entities;
00066 }
00067
00068 newent = NULL;
00069 oldent = NULL;
00070 newindex = 0;
00071 oldindex = 0;
00072 while ( newindex < to->num_entities || oldindex < from_num_entities ) {
00073 if ( newindex >= to->num_entities ) {
00074 newnum = 9999;
00075 } else {
00076 newent = &svs.snapshotEntities[(to->first_entity+newindex) % svs.numSnapshotEntities];
00077 newnum = newent->number;
00078 }
00079
00080 if ( oldindex >= from_num_entities ) {
00081 oldnum = 9999;
00082 } else {
00083 oldent = &svs.snapshotEntities[(from->first_entity+oldindex) % svs.numSnapshotEntities];
00084 oldnum = oldent->number;
00085 }
00086
00087 if ( newnum == oldnum ) {
00088 // delta update from old position
00089 // because the force parm is qfalse, this will not result
00090 // in any bytes being emited if the entity has not changed at all
00091 MSG_WriteDeltaEntity (msg, oldent, newent, qfalse );
00092 oldindex++;
00093 newindex++;
00094 continue;
00095 }
00096
00097 if ( newnum < oldnum ) {
00098 // this is a new entity, send it from the baseline
00099 MSG_WriteDeltaEntity (msg, &sv.svEntities[newnum].baseline, newent, qtrue );
00100 newindex++;
00101 continue;
00102 }
00103
00104 if ( newnum > oldnum ) {
00105 // the old entity isn't present in the new message
00106 MSG_WriteDeltaEntity (msg, oldent, NULL, qtrue );
00107 oldindex++;
00108 continue;
00109 }
00110 }
00111
00112 MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS ); // end of packetentities
00113 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 239 of file sv_snapshot.c. References Com_Error(), ERR_DROP, and QDECL. Referenced by SV_BuildClientSnapshot(). 00239 {
00240 int *ea, *eb;
00241
00242 ea = (int *)a;
00243 eb = (int *)b;
00244
00245 if ( *ea == *eb ) {
00246 Com_Error( ERR_DROP, "SV_QsortEntityStates: duplicated entity" );
00247 }
00248
00249 if ( *ea < *eb ) {
00250 return -1;
00251 }
00252
00253 return 1;
00254 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 527 of file sv_snapshot.c. References client_t, Cvar_Set(), cvar_s::integer, client_s::rate, and sv_maxRate. Referenced by SV_SendClientMessages(), and SV_SendMessageToClient(). 00527 {
00528 int rate;
00529 int rateMsec;
00530
00531 // individual messages will never be larger than fragment size
00532 if ( messageSize > 1500 ) {
00533 messageSize = 1500;
00534 }
00535 rate = client->rate;
00536 if ( sv_maxRate->integer ) {
00537 if ( sv_maxRate->integer < 1000 ) {
00538 Cvar_Set( "sv_MaxRate", "1000" );
00539 }
00540 if ( sv_maxRate->integer < rate ) {
00541 rate = sv_maxRate->integer;
00542 }
00543 }
00544 rateMsec = ( messageSize + HEADER_RATE_BYTES ) * 1000 / rate;
00545
00546 return rateMsec;
00547 }
|
Here is the call graph for this function:

|
|
Definition at line 655 of file sv_snapshot.c. References c, client_t, serverStatic_t::clients, i, cvar_s::integer, client_s::netchan, client_s::nextSnapshotTime, client_s::state, sv_maxclients, SV_Netchan_TransmitNextFragment(), SV_RateMsec(), SV_SendClientSnapshot(), svs, serverStatic_t::time, netchan_t::unsentFragments, netchan_t::unsentFragmentStart, and netchan_t::unsentLength. Referenced by SV_Frame(). 00655 {
00656 int i;
00657 client_t *c;
00658
00659 // send a message to each connected client
00660 for (i=0, c = svs.clients ; i < sv_maxclients->integer ; i++, c++) {
00661 if (!c->state) {
00662 continue; // not connected
00663 }
00664
00665 if ( svs.time < c->nextSnapshotTime ) {
00666 continue; // not time yet
00667 }
00668
00669 // send additional message fragments if the last message
00670 // was too large to send at once
00671 if ( c->netchan.unsentFragments ) {
00672 c->nextSnapshotTime = svs.time +
00673 SV_RateMsec( c, c->netchan.unsentLength - c->netchan.unsentFragmentStart );
00674 SV_Netchan_TransmitNextFragment( c );
00675 continue;
00676 }
00677
00678 // generate and send a new message
00679 SV_SendClientSnapshot( c );
00680 }
00681 }
|
Here is the call graph for this function:

|
|
Definition at line 610 of file sv_snapshot.c. References msg_t::allowoverflow, byte, client_t, Com_Printf(), client_s::gentity, client_s::lastClientCommand, MSG_Clear(), MSG_Init(), MSG_WriteLong(), client_s::name, msg_t::overflowed, sharedEntity_t::r, SV_BuildClientSnapshot(), SV_SendMessageToClient(), SV_UpdateServerCommandsToClient(), SV_WriteDownloadToClient(), SV_WriteSnapshotToClient(), and entityShared_t::svFlags. Referenced by SV_FinalMessage(), SV_SendClientMessages(), and SV_VerifyPaks_f(). 00610 {
00611 byte msg_buf[MAX_MSGLEN];
00612 msg_t msg;
00613
00614 // build the snapshot
00615 SV_BuildClientSnapshot( client );
00616
00617 // bots need to have their snapshots build, but
00618 // the query them directly without needing to be sent
00619 if ( client->gentity && client->gentity->r.svFlags & SVF_BOT ) {
00620 return;
00621 }
00622
00623 MSG_Init (&msg, msg_buf, sizeof(msg_buf));
00624 msg.allowoverflow = qtrue;
00625
00626 // NOTE, MRE: all server->client messages now acknowledge
00627 // let the client know which reliable clientCommands we have received
00628 MSG_WriteLong( &msg, client->lastClientCommand );
00629
00630 // (re)send any reliable server commands
00631 SV_UpdateServerCommandsToClient( client, &msg );
00632
00633 // send over all the relevant entityState_t
00634 // and the playerState_t
00635 SV_WriteSnapshotToClient( client, &msg );
00636
00637 // Add any download data if the client is downloading
00638 SV_WriteDownloadToClient( client, &msg );
00639
00640 // check for overflow
00641 if ( msg.overflowed ) {
00642 Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
00643 MSG_Clear (&msg);
00644 }
00645
00646 SV_SendMessageToClient( &msg, client );
00647 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 556 of file sv_snapshot.c. References client_t, msg_t::cursize, client_s::downloadName, client_s::frames, cvar_s::integer, clientSnapshot_t::messageAcked, clientSnapshot_t::messageSent, clientSnapshot_t::messageSize, NA_LOOPBACK, client_s::netchan, client_s::nextSnapshotTime, netchan_t::outgoingSequence, client_s::rateDelayed, netchan_t::remoteAddress, client_s::snapshotMsec, client_s::state, sv_lanForceRate, SV_Netchan_Transmit(), SV_RateMsec(), svs, Sys_IsLANAddress(), serverStatic_t::time, and netadr_t::type. Referenced by SV_SendClientGameState(), and SV_SendClientSnapshot(). 00556 {
00557 int rateMsec;
00558
00559 // record information about the message
00560 client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSize = msg->cursize;
00561 client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSent = svs.time;
00562 client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageAcked = -1;
00563
00564 // send the datagram
00565 SV_Netchan_Transmit( client, msg ); //msg->cursize, msg->data );
00566
00567 // set nextSnapshotTime based on rate and requested number of updates
00568
00569 // local clients get snapshots every frame
00570 // TTimo - https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
00571 // added sv_lanForceRate check
00572 if ( client->netchan.remoteAddress.type == NA_LOOPBACK || (sv_lanForceRate->integer && Sys_IsLANAddress (client->netchan.remoteAddress)) ) {
00573 client->nextSnapshotTime = svs.time - 1;
00574 return;
00575 }
00576
00577 // normal rate / snapshotMsec calculation
00578 rateMsec = SV_RateMsec( client, msg->cursize );
00579
00580 if ( rateMsec < client->snapshotMsec ) {
00581 // never send more packets than this, no matter what the rate is at
00582 rateMsec = client->snapshotMsec;
00583 client->rateDelayed = qfalse;
00584 } else {
00585 client->rateDelayed = qtrue;
00586 }
00587
00588 client->nextSnapshotTime = svs.time + rateMsec;
00589
00590 // don't pile up empty snapshots while connecting
00591 if ( client->state != CS_ACTIVE ) {
00592 // a gigantic connection message may have already put the nextSnapshotTime
00593 // more than a second away, so don't shorten it
00594 // do shorten if client is downloading
00595 if ( !*client->downloadName && client->nextSnapshotTime < svs.time + 1000 ) {
00596 client->nextSnapshotTime = svs.time + 1000;
00597 }
00598 }
00599 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 208 of file sv_snapshot.c. References client_t, i, MAX_RELIABLE_COMMANDS, MSG_WriteByte(), MSG_WriteLong(), MSG_WriteString(), client_s::reliableAcknowledge, client_s::reliableCommands, client_s::reliableSent, client_s::reliableSequence, and svc_serverCommand. Referenced by SV_SendClientGameState(), and SV_SendClientSnapshot(). 00208 {
00209 int i;
00210
00211 // write any unacknowledged serverCommands
00212 for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
00213 MSG_WriteByte( msg, svc_serverCommand );
00214 MSG_WriteLong( msg, i );
00215 MSG_WriteString( msg, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
00216 }
00217 client->reliableSent = client->reliableSequence;
00218 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 122 of file sv_snapshot.c. References clientSnapshot_t::areabits, clientSnapshot_t::areabytes, client_t, Com_DPrintf(), client_s::deltaMessage, clientSnapshot_t::first_entity, client_s::frames, i, cvar_s::integer, MSG_WriteByte(), MSG_WriteData(), MSG_WriteDeltaPlayerstate(), MSG_WriteLong(), client_s::name, client_s::netchan, serverStatic_t::nextSnapshotEntities, NULL, serverStatic_t::numSnapshotEntities, netchan_t::outgoingSequence, PACKET_BACKUP, clientSnapshot_t::ps, client_s::rateDelayed, serverStatic_t::snapFlagServerBit, client_s::state, SV_EmitPacketEntities(), sv_padPackets, svc_nop, svc_snapshot, svs, and serverStatic_t::time. Referenced by SV_SendClientSnapshot(). 00122 {
00123 clientSnapshot_t *frame, *oldframe;
00124 int lastframe;
00125 int i;
00126 int snapFlags;
00127
00128 // this is the snapshot we are creating
00129 frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
00130
00131 // try to use a previous frame as the source for delta compressing the snapshot
00132 if ( client->deltaMessage <= 0 || client->state != CS_ACTIVE ) {
00133 // client is asking for a retransmit
00134 oldframe = NULL;
00135 lastframe = 0;
00136 } else if ( client->netchan.outgoingSequence - client->deltaMessage
00137 >= (PACKET_BACKUP - 3) ) {
00138 // client hasn't gotten a good message through in a long time
00139 Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
00140 oldframe = NULL;
00141 lastframe = 0;
00142 } else {
00143 // we have a valid snapshot to delta from
00144 oldframe = &client->frames[ client->deltaMessage & PACKET_MASK ];
00145 lastframe = client->netchan.outgoingSequence - client->deltaMessage;
00146
00147 // the snapshot's entities may still have rolled off the buffer, though
00148 if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
00149 Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
00150 oldframe = NULL;
00151 lastframe = 0;
00152 }
00153 }
00154
00155 MSG_WriteByte (msg, svc_snapshot);
00156
00157 // NOTE, MRE: now sent at the start of every message from server to client
00158 // let the client know which reliable clientCommands we have received
00159 //MSG_WriteLong( msg, client->lastClientCommand );
00160
00161 // send over the current server time so the client can drift
00162 // its view of time to try to match
00163 MSG_WriteLong (msg, svs.time);
00164
00165 // what we are delta'ing from
00166 MSG_WriteByte (msg, lastframe);
00167
00168 snapFlags = svs.snapFlagServerBit;
00169 if ( client->rateDelayed ) {
00170 snapFlags |= SNAPFLAG_RATE_DELAYED;
00171 }
00172 if ( client->state != CS_ACTIVE ) {
00173 snapFlags |= SNAPFLAG_NOT_ACTIVE;
00174 }
00175
00176 MSG_WriteByte (msg, snapFlags);
00177
00178 // send over the areabits
00179 MSG_WriteByte (msg, frame->areabytes);
00180 MSG_WriteData (msg, frame->areabits, frame->areabytes);
00181
00182 // delta encode the playerstate
00183 if ( oldframe ) {
00184 MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
00185 } else {
00186 MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
00187 }
00188
00189 // delta encode the entities
00190 SV_EmitPacketEntities (oldframe, frame, msg);
00191
00192 // padding for rate debugging
00193 if ( sv_padPackets->integer ) {
00194 for ( i = 0 ; i < sv_padPackets->integer ; i++ ) {
00195 MSG_WriteByte (msg, svc_nop);
00196 }
00197 }
00198 }
|
Here is the call graph for this function:

1.3.9.1