sv_snapshot.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. // leave this as first line for PCH reasons...
  2. //
  3. #include "../server/exe_headers.h"
  4. #include "..\client\vmachine.h"
  5. #include "server.h"
  6. /*
  7. =============================================================================
  8. Delta encode a client frame onto the network channel
  9. A normal server packet will look like:
  10. 4 sequence number (high bit set if an oversize fragment)
  11. <optional reliable commands>
  12. 1 svc_snapshot
  13. 4 last client reliable command
  14. 4 serverTime
  15. 1 lastframe for delta compression
  16. 1 snapFlags
  17. 1 areaBytes
  18. <areabytes>
  19. <playerstate>
  20. <packetentities>
  21. =============================================================================
  22. */
  23. /*
  24. =============
  25. SV_EmitPacketEntities
  26. Writes a delta update of an entityState_t list to the message.
  27. =============
  28. */
  29. static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg ) {
  30. entityState_t *oldent, *newent;
  31. int oldindex, newindex;
  32. int oldnum, newnum;
  33. int from_num_entities;
  34. // generate the delta update
  35. if ( !from ) {
  36. from_num_entities = 0;
  37. } else {
  38. from_num_entities = from->num_entities;
  39. }
  40. newent = NULL;
  41. oldent = NULL;
  42. newindex = 0;
  43. oldindex = 0;
  44. const int num2Send = to->num_entities >= svs.numSnapshotEntities ? svs.numSnapshotEntities : to->num_entities;
  45. while ( newindex < num2Send || oldindex < from_num_entities ) {
  46. if ( newindex >= num2Send ) {
  47. newnum = 9999;
  48. } else {
  49. newent = &svs.snapshotEntities[(to->first_entity+newindex) % svs.numSnapshotEntities];
  50. newnum = newent->number;
  51. }
  52. if ( oldindex >= from_num_entities ) {
  53. oldnum = 9999;
  54. } else {
  55. oldent = &svs.snapshotEntities[(from->first_entity+oldindex) % svs.numSnapshotEntities];
  56. oldnum = oldent->number;
  57. }
  58. if ( newnum == oldnum ) {
  59. // delta update from old position
  60. // because the force parm is qfalse, this will not result
  61. // in any bytes being emited if the entity has not changed at all
  62. MSG_WriteEntity(msg, newent, 0);
  63. oldindex++;
  64. newindex++;
  65. continue;
  66. }
  67. if ( newnum < oldnum ) {
  68. // this is a new entity, send it from the baseline
  69. MSG_WriteEntity (msg, newent, 0);
  70. newindex++;
  71. continue;
  72. }
  73. if ( newnum > oldnum ) {
  74. // the old entity isn't present in the new message
  75. if(oldent) {
  76. MSG_WriteEntity (msg, NULL, oldent->number);
  77. }
  78. oldindex++;
  79. continue;
  80. }
  81. }
  82. MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS ); // end of packetentities
  83. }
  84. /*
  85. ==================
  86. SV_WriteSnapshotToClient
  87. ==================
  88. */
  89. static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
  90. clientSnapshot_t *frame, *oldframe;
  91. int lastframe;
  92. int snapFlags;
  93. // this is the snapshot we are creating
  94. frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
  95. // try to use a previous frame as the source for delta compressing the snapshot
  96. if ( client->deltaMessage <= 0 || client->state != CS_ACTIVE ) {
  97. // client is asking for a retransmit
  98. oldframe = NULL;
  99. lastframe = 0;
  100. } else if ( client->netchan.outgoingSequence - client->deltaMessage
  101. >= (PACKET_BACKUP - 3) ) {
  102. // client hasn't gotten a good message through in a long time
  103. Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
  104. oldframe = NULL;
  105. lastframe = 0;
  106. } else {
  107. // we have a valid snapshot to delta from
  108. oldframe = &client->frames[ client->deltaMessage & PACKET_MASK ];
  109. lastframe = client->netchan.outgoingSequence - client->deltaMessage;
  110. // the snapshot's entities may still have rolled off the buffer, though
  111. if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
  112. Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
  113. oldframe = NULL;
  114. lastframe = 0;
  115. }
  116. }
  117. MSG_WriteByte (msg, svc_snapshot);
  118. // let the client know which reliable clientCommands we have received
  119. MSG_WriteLong( msg, client->lastClientCommand );
  120. // send over the current server time so the client can drift
  121. // its view of time to try to match
  122. MSG_WriteLong (msg, sv.time);
  123. // we must write a message number, because recorded demos won't have
  124. // the same network message sequences
  125. MSG_WriteLong (msg, client->netchan.outgoingSequence );
  126. MSG_WriteByte (msg, lastframe); // what we are delta'ing from
  127. MSG_WriteLong (msg, client->cmdNum); // we have executed up to here
  128. snapFlags = client->rateDelayed | ( client->droppedCommands << 1 );
  129. client->droppedCommands = 0;
  130. MSG_WriteByte (msg, snapFlags);
  131. // send over the areabits
  132. MSG_WriteByte (msg, frame->areabytes);
  133. MSG_WriteData (msg, frame->areabits, frame->areabytes);
  134. // delta encode the playerstate
  135. if ( oldframe ) {
  136. MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
  137. } else {
  138. MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
  139. }
  140. // delta encode the entities
  141. SV_EmitPacketEntities (oldframe, frame, msg);
  142. }
  143. /*
  144. ==================
  145. SV_UpdateServerCommandsToClient
  146. (re)send all server commands the client hasn't acknowledged yet
  147. ==================
  148. */
  149. static void SV_UpdateServerCommandsToClient( client_t *client, msg_t *msg ) {
  150. int i;
  151. // write any unacknowledged serverCommands
  152. for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
  153. MSG_WriteByte( msg, svc_serverCommand );
  154. MSG_WriteLong( msg, i );
  155. MSG_WriteString( msg, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
  156. }
  157. }
  158. /*
  159. =============================================================================
  160. Build a client snapshot structure
  161. =============================================================================
  162. */
  163. #define MAX_SNAPSHOT_ENTITIES 1024
  164. typedef struct {
  165. int numSnapshotEntities;
  166. int snapshotEntities[MAX_SNAPSHOT_ENTITIES];
  167. } snapshotEntityNumbers_t;
  168. /*
  169. =======================
  170. SV_QsortEntityNumbers
  171. =======================
  172. */
  173. static int SV_QsortEntityNumbers( const void *a, const void *b ) {
  174. int *ea, *eb;
  175. ea = (int *)a;
  176. eb = (int *)b;
  177. if ( *ea == *eb ) {
  178. Com_Error( ERR_DROP, "SV_QsortEntityStates: duplicated entity" );
  179. }
  180. if ( *ea < *eb ) {
  181. return -1;
  182. }
  183. return 1;
  184. }
  185. /*
  186. ===============
  187. SV_AddEntToSnapshot
  188. ===============
  189. */
  190. static void SV_AddEntToSnapshot( svEntity_t *svEnt, gentity_t *gEnt, snapshotEntityNumbers_t *eNums ) {
  191. // if we have already added this entity to this snapshot, don't add again
  192. if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
  193. return;
  194. }
  195. svEnt->snapshotCounter = sv.snapshotCounter;
  196. // if we are full, silently discard entities
  197. if ( eNums->numSnapshotEntities == MAX_SNAPSHOT_ENTITIES ) {
  198. return;
  199. }
  200. if (sv.snapshotCounter &1 && eNums->numSnapshotEntities == svs.numSnapshotEntities-1)
  201. { //we're full, and about to wrap around and stomp ents, so half the time send the first set without stomping.
  202. return;
  203. }
  204. eNums->snapshotEntities[ eNums->numSnapshotEntities ] = gEnt->s.number;
  205. eNums->numSnapshotEntities++;
  206. }
  207. //rww - bg_public.h won't cooperate in here
  208. #define EF_PERMANENT 0x00080000
  209. float sv_sightRangeForLevel[6] =
  210. {
  211. 0,//FORCE_LEVEL_0
  212. 1024.f, //FORCE_LEVEL_1
  213. 2048.0f,//FORCE_LEVEL_2
  214. 4096.0f,//FORCE_LEVEL_3
  215. 4096.0f,//FORCE_LEVEL_4
  216. 4096.0f//FORCE_LEVEL_5
  217. };
  218. qboolean SV_PlayerCanSeeEnt( gentity_t *ent, int sightLevel )
  219. {//return true if this ent is in view
  220. //NOTE: this is similar to the func CG_PlayerCanSeeCent in cg_players
  221. vec3_t viewOrg, viewAngles, viewFwd, dir2Ent;
  222. if ( !ent )
  223. {
  224. return qfalse;
  225. }
  226. if ( VM_Call( CG_CAMERA_POS, viewOrg))
  227. {
  228. if ( VM_Call( CG_CAMERA_ANG, viewAngles))
  229. {
  230. float dot = 0.25f;//1.0f;
  231. float range = sv_sightRangeForLevel[sightLevel];
  232. VectorSubtract( ent->currentOrigin, viewOrg, dir2Ent );
  233. float entDist = VectorNormalize( dir2Ent );
  234. if ( (ent->s.eFlags&EF_FORCE_VISIBLE) )
  235. {//no dist check on them?
  236. }
  237. else
  238. {
  239. if ( entDist < 128.0f )
  240. {//can always see them if they're really close
  241. return qtrue;
  242. }
  243. if ( entDist > range )
  244. {//too far away to see them
  245. return qfalse;
  246. }
  247. }
  248. dot += (0.99f-dot)*entDist/range;//the farther away they are, the more in front they have to be
  249. AngleVectors( viewAngles, viewFwd, NULL, NULL );
  250. if ( DotProduct( viewFwd, dir2Ent ) < dot )
  251. {
  252. return qfalse;
  253. }
  254. return qtrue;
  255. }
  256. }
  257. return qfalse;
  258. }
  259. /*
  260. ===============
  261. SV_AddEntitiesVisibleFromPoint
  262. ===============
  263. */
  264. static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame,
  265. snapshotEntityNumbers_t *eNums, qboolean portal ) {
  266. int e, i;
  267. gentity_t *ent;
  268. svEntity_t *svEnt;
  269. int l;
  270. int clientarea, clientcluster;
  271. int leafnum;
  272. int c_fullsend;
  273. const byte *clientpvs;
  274. const byte *bitvector;
  275. qboolean sightOn = qfalse;
  276. // during an error shutdown message we may need to transmit
  277. // the shutdown message after the server has shutdown, so
  278. // specfically check for it
  279. if ( !sv.state ) {
  280. return;
  281. }
  282. leafnum = CM_PointLeafnum (origin);
  283. clientarea = CM_LeafArea (leafnum);
  284. clientcluster = CM_LeafCluster (leafnum);
  285. // calculate the visible areas
  286. frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );
  287. clientpvs = CM_ClusterPVS (clientcluster);
  288. c_fullsend = 0;
  289. if ( !portal )
  290. {//not if this if through a portal...??? James said to do this...
  291. if ( (frame->ps.forcePowersActive&(1<<FP_SEE)) )
  292. {
  293. sightOn = qtrue;
  294. }
  295. }
  296. for ( e = 0 ; e < ge->num_entities ; e++ ) {
  297. ent = SV_GentityNum(e);
  298. if (!ent->inuse) {
  299. continue;
  300. }
  301. if (ent->s.eFlags & EF_PERMANENT)
  302. { // he's permanent, so don't send him down!
  303. continue;
  304. }
  305. if (ent->s.number != e) {
  306. Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
  307. ent->s.number = e;
  308. }
  309. // never send entities that aren't linked in
  310. if ( !ent->linked ) {
  311. continue;
  312. }
  313. // entities can be flagged to explicitly not be sent to the client
  314. if ( ent->svFlags & SVF_NOCLIENT ) {
  315. continue;
  316. }
  317. svEnt = SV_SvEntityForGentity( ent );
  318. // don't double add an entity through portals
  319. if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
  320. continue;
  321. }
  322. // broadcast entities are always sent, and so is the main player so we don't see noclip weirdness
  323. if ( ent->svFlags & SVF_BROADCAST || !e) {
  324. SV_AddEntToSnapshot( svEnt, ent, eNums );
  325. continue;
  326. }
  327. if (ent->s.isPortalEnt)
  328. { //rww - portal entities are always sent as well
  329. SV_AddEntToSnapshot( svEnt, ent, eNums );
  330. continue;
  331. }
  332. if ( sightOn )
  333. {//force sight is on, sees through portals, so draw them always if in radius
  334. if ( SV_PlayerCanSeeEnt( ent, frame->ps.forcePowerLevel[FP_SEE] ) )
  335. {//entity is visible
  336. SV_AddEntToSnapshot( svEnt, ent, eNums );
  337. continue;
  338. }
  339. }
  340. // ignore if not touching a PV leaf
  341. // check area
  342. if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
  343. // doors can legally straddle two areas, so
  344. // we may need to check another one
  345. if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
  346. continue; // blocked by a door
  347. }
  348. }
  349. bitvector = clientpvs;
  350. // check individual leafs
  351. if ( !svEnt->numClusters ) {
  352. continue;
  353. }
  354. l = 0;
  355. #ifdef _XBOX
  356. if(bitvector) {
  357. #endif
  358. for ( i=0 ; i < svEnt->numClusters ; i++ ) {
  359. l = svEnt->clusternums[i];
  360. if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
  361. break;
  362. }
  363. }
  364. #ifdef _XBOX
  365. }
  366. #endif
  367. // if we haven't found it to be visible,
  368. // check overflow clusters that coudln't be stored
  369. #ifdef _XBOX
  370. if ( bitvector && i == svEnt->numClusters ) {
  371. #else
  372. if ( i == svEnt->numClusters ) {
  373. #endif
  374. if ( svEnt->lastCluster ) {
  375. for ( ; l <= svEnt->lastCluster ; l++ ) {
  376. if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
  377. break;
  378. }
  379. }
  380. if ( l == svEnt->lastCluster ) {
  381. continue; // not visible
  382. }
  383. } else {
  384. continue;
  385. }
  386. }
  387. // add it
  388. SV_AddEntToSnapshot( svEnt, ent, eNums );
  389. // if its a portal entity, add everything visible from its camera position
  390. if ( ent->svFlags & SVF_PORTAL ) {
  391. SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
  392. #ifdef _XBOX
  393. //Must get clientpvs again since above call destroyed it.
  394. clientpvs = CM_ClusterPVS (clientcluster);
  395. #endif
  396. }
  397. }
  398. }
  399. /*
  400. =============
  401. SV_BuildClientSnapshot
  402. Decides which entities are going to be visible to the client, and
  403. copies off the playerstate and areabits.
  404. This properly handles multiple recursive portals, but the render
  405. currently doesn't.
  406. For viewing through other player's eyes, clent can be something other than client->gentity
  407. =============
  408. */
  409. static clientSnapshot_t *SV_BuildClientSnapshot( client_t *client ) {
  410. vec3_t org;
  411. clientSnapshot_t *frame;
  412. snapshotEntityNumbers_t entityNumbers;
  413. int i;
  414. gentity_t *ent;
  415. entityState_t *state;
  416. gentity_t *clent;
  417. // bump the counter used to prevent double adding
  418. sv.snapshotCounter++;
  419. // this is the frame we are creating
  420. frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
  421. // clear everything in this snapshot
  422. entityNumbers.numSnapshotEntities = 0;
  423. memset( frame->areabits, 0, sizeof( frame->areabits ) );
  424. clent = client->gentity;
  425. if ( !clent ) {
  426. return frame;
  427. }
  428. // grab the current playerState_t
  429. frame->ps = *clent->client;
  430. // this stops the main client entity playerstate from being sent across, which has the effect of breaking
  431. // looping sounds for the main client. So I took it out.
  432. /* {
  433. int clientNum;
  434. svEntity_t *svEnt;
  435. clientNum = frame->ps.clientNum;
  436. if ( clientNum < 0 || clientNum >= MAX_GENTITIES ) {
  437. Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" );
  438. }
  439. svEnt = &sv.svEntities[ clientNum ];
  440. // never send client's own entity, because it can
  441. // be regenerated from the playerstate
  442. svEnt->snapshotCounter = sv.snapshotCounter;
  443. }
  444. */
  445. // find the client's viewpoint
  446. //if in camera mode use camera position instead
  447. if ( VM_Call( CG_CAMERA_POS, org))
  448. {
  449. //org[2] += clent->client->viewheight;
  450. }
  451. else
  452. {
  453. VectorCopy( clent->client->origin, org );
  454. org[2] += clent->client->viewheight;
  455. //============
  456. // need to account for lean, or areaportal doors don't draw properly... -slc
  457. if (frame->ps.leanofs != 0)
  458. {
  459. vec3_t right;
  460. //add leaning offset
  461. vec3_t v3ViewAngles;
  462. VectorCopy(clent->client->viewangles, v3ViewAngles);
  463. v3ViewAngles[2] += (float)frame->ps.leanofs/2;
  464. AngleVectors(v3ViewAngles, NULL, right, NULL);
  465. VectorMA(org, (float)frame->ps.leanofs, right, org);
  466. }
  467. //============
  468. }
  469. VectorCopy( org, frame->ps.serverViewOrg );
  470. VectorCopy( org, clent->client->serverViewOrg );
  471. // add all the entities directly visible to the eye, which
  472. // may include portal entities that merge other viewpoints
  473. SV_AddEntitiesVisibleFromPoint( org, frame, &entityNumbers, qfalse );
  474. /*
  475. //was in here for debugging- print list of all entities in snapshot when you go over the limit
  476. if ( entityNumbers.numSnapshotEntities >= 256 )
  477. {
  478. for ( int xxx = 0; xxx < entityNumbers.numSnapshotEntities; xxx++ )
  479. {
  480. Com_Printf("%d - ", xxx );
  481. ge->PrintEntClassname( entityNumbers.snapshotEntities[xxx] );
  482. }
  483. }
  484. else if ( entityNumbers.numSnapshotEntities >= 200 )
  485. {
  486. Com_Printf(S_COLOR_RED"%d snapshot entities!", entityNumbers.numSnapshotEntities );
  487. }
  488. else if ( entityNumbers.numSnapshotEntities >= 128 )
  489. {
  490. Com_Printf(S_COLOR_YELLOW"%d snapshot entities", entityNumbers.numSnapshotEntities );
  491. }
  492. */
  493. // if there were portals visible, there may be out of order entities
  494. // in the list which will need to be resorted for the delta compression
  495. // to work correctly. This also catches the error condition
  496. // of an entity being included twice.
  497. qsort( entityNumbers.snapshotEntities, entityNumbers.numSnapshotEntities,
  498. sizeof( entityNumbers.snapshotEntities[0] ), SV_QsortEntityNumbers );
  499. // now that all viewpoint's areabits have been OR'd together, invert
  500. // all of them to make it a mask vector, which is what the renderer wants
  501. for ( i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++ ) {
  502. ((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
  503. }
  504. // copy the entity states out
  505. frame->num_entities = 0;
  506. frame->first_entity = svs.nextSnapshotEntities;
  507. for ( i = 0 ; i < entityNumbers.numSnapshotEntities ; i++ ) {
  508. ent = SV_GentityNum(entityNumbers.snapshotEntities[i]);
  509. state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
  510. *state = ent->s;
  511. svs.nextSnapshotEntities++;
  512. frame->num_entities++;
  513. }
  514. return frame;
  515. }
  516. /*
  517. =======================
  518. SV_SendMessageToClient
  519. Called by SV_SendClientSnapshot and SV_SendClientGameState
  520. =======================
  521. */
  522. #define HEADER_RATE_BYTES 48 // include our header, IP header, and some overhead
  523. void SV_SendMessageToClient( msg_t *msg, client_t *client ) {
  524. int rateMsec;
  525. // record information about the message
  526. client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSize = msg->cursize;
  527. client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSent = sv.time;
  528. // send the datagram
  529. Netchan_Transmit( &client->netchan, msg->cursize, msg->data );
  530. // set nextSnapshotTime based on rate and requested number of updates
  531. // local clients get snapshots every frame (FIXME: also treat LAN clients)
  532. if ( client->netchan.remoteAddress.type == NA_LOOPBACK ) {
  533. client->nextSnapshotTime = sv.time - 1;
  534. return;
  535. }
  536. // normal rate / snapshotMsec calculation
  537. rateMsec = ( msg->cursize + HEADER_RATE_BYTES ) * 1000 / client->rate;
  538. if ( rateMsec < client->snapshotMsec ) {
  539. rateMsec = client->snapshotMsec;
  540. client->rateDelayed = qfalse;
  541. } else {
  542. client->rateDelayed = qtrue;
  543. }
  544. client->nextSnapshotTime = sv.time + rateMsec;
  545. // if we haven't gotten a message from the client in over a second, we will
  546. // drop to only sending one snapshot a second until they timeout
  547. if ( sv.time - client->lastPacketTime > 1000 || client->state != CS_ACTIVE ) {
  548. if ( client->nextSnapshotTime < sv.time + 1000 ) {
  549. client->nextSnapshotTime = sv.time + 1000;
  550. }
  551. return;
  552. }
  553. }
  554. /*
  555. =======================
  556. SV_SendClientEmptyMessage
  557. This is just an empty message so that we can tell if
  558. the client dropped the gamestate that went out before
  559. =======================
  560. */
  561. void SV_SendClientEmptyMessage( client_t *client ) {
  562. msg_t msg;
  563. byte buffer[10];
  564. MSG_Init( &msg, buffer, sizeof( buffer ) );
  565. SV_SendMessageToClient( &msg, client );
  566. }
  567. /*
  568. =======================
  569. SV_SendClientSnapshot
  570. =======================
  571. */
  572. void SV_SendClientSnapshot( client_t *client ) {
  573. byte msg_buf[MAX_MSGLEN];
  574. msg_t msg;
  575. // build the snapshot
  576. SV_BuildClientSnapshot( client );
  577. // bots need to have their snapshots build, but
  578. // the query them directly without needing to be sent
  579. if ( client->gentity && client->gentity->svFlags & SVF_BOT ) {
  580. return;
  581. }
  582. MSG_Init (&msg, msg_buf, sizeof(msg_buf));
  583. msg.allowoverflow = qtrue;
  584. // (re)send any reliable server commands
  585. SV_UpdateServerCommandsToClient( client, &msg );
  586. // send over all the relevant entityState_t
  587. // and the playerState_t
  588. SV_WriteSnapshotToClient( client, &msg );
  589. // check for overflow
  590. if ( msg.overflowed ) {
  591. Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
  592. MSG_Clear (&msg);
  593. }
  594. SV_SendMessageToClient( &msg, client );
  595. }
  596. /*
  597. =======================
  598. SV_SendClientMessages
  599. =======================
  600. */
  601. void SV_SendClientMessages( void ) {
  602. int i;
  603. client_t *c;
  604. // send a message to each connected client
  605. for (i=0, c = svs.clients ; i < 1 ; i++, c++) {
  606. if (!c->state) {
  607. continue; // not connected
  608. }
  609. if ( sv.time < c->nextSnapshotTime ) {
  610. continue; // not time yet
  611. }
  612. if ( c->state != CS_ACTIVE ) {
  613. if ( c->state != CS_ZOMBIE ) {
  614. SV_SendClientEmptyMessage( c );
  615. }
  616. continue;
  617. }
  618. SV_SendClientSnapshot( c );
  619. }
  620. }