sv_ents.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "server.h"
  16. /*
  17. =============================================================================
  18. Encode a client frame onto the network channel
  19. =============================================================================
  20. */
  21. #if 0
  22. // because there can be a lot of projectiles, there is a special
  23. // network protocol for them
  24. #define MAX_PROJECTILES 64
  25. edict_t *projectiles[MAX_PROJECTILES];
  26. int numprojs;
  27. cvar_t *sv_projectiles;
  28. qboolean SV_AddProjectileUpdate (edict_t *ent)
  29. {
  30. if (!sv_projectiles)
  31. sv_projectiles = Cvar_Get("sv_projectiles", "1", 0);
  32. if (!sv_projectiles->value)
  33. return false;
  34. if (!(ent->svflags & SVF_PROJECTILE))
  35. return false;
  36. if (numprojs == MAX_PROJECTILES)
  37. return true;
  38. projectiles[numprojs++] = ent;
  39. return true;
  40. }
  41. void SV_EmitProjectileUpdate (sizebuf_t *msg)
  42. {
  43. byte bits[16]; // [modelindex] [48 bits] xyz p y 12 12 12 8 8 [entitynum] [e2]
  44. int n, i;
  45. edict_t *ent;
  46. int x, y, z, p, yaw;
  47. int len;
  48. if (!numprojs)
  49. return;
  50. MSG_WriteByte (msg, numprojs);
  51. for (n=0 ; n<numprojs ; n++)
  52. {
  53. ent = projectiles[n];
  54. x = (int)(ent->s.origin[0]+4096)>>1;
  55. y = (int)(ent->s.origin[1]+4096)>>1;
  56. z = (int)(ent->s.origin[2]+4096)>>1;
  57. p = (int)(256*ent->s.angles[0]/360)&255;
  58. yaw = (int)(256*ent->s.angles[1]/360)&255;
  59. len = 0;
  60. bits[len++] = x;
  61. bits[len++] = (x>>8) | (y<<4);
  62. bits[len++] = (y>>4);
  63. bits[len++] = z;
  64. bits[len++] = (z>>8);
  65. if (ent->s.effects & EF_BLASTER)
  66. bits[len-1] |= 64;
  67. if (ent->s.old_origin[0] != ent->s.origin[0] ||
  68. ent->s.old_origin[1] != ent->s.origin[1] ||
  69. ent->s.old_origin[2] != ent->s.origin[2]) {
  70. bits[len-1] |= 128;
  71. x = (int)(ent->s.old_origin[0]+4096)>>1;
  72. y = (int)(ent->s.old_origin[1]+4096)>>1;
  73. z = (int)(ent->s.old_origin[2]+4096)>>1;
  74. bits[len++] = x;
  75. bits[len++] = (x>>8) | (y<<4);
  76. bits[len++] = (y>>4);
  77. bits[len++] = z;
  78. bits[len++] = (z>>8);
  79. }
  80. bits[len++] = p;
  81. bits[len++] = yaw;
  82. bits[len++] = ent->s.modelindex;
  83. bits[len++] = (ent->s.number & 0x7f);
  84. if (ent->s.number > 255) {
  85. bits[len-1] |= 128;
  86. bits[len++] = (ent->s.number >> 7);
  87. }
  88. for (i=0 ; i<len ; i++)
  89. MSG_WriteByte (msg, bits[i]);
  90. }
  91. }
  92. #endif
  93. /*
  94. =============
  95. SV_EmitPacketEntities
  96. Writes a delta update of an entity_state_t list to the message.
  97. =============
  98. */
  99. void SV_EmitPacketEntities (client_frame_t *from, client_frame_t *to, sizebuf_t *msg)
  100. {
  101. entity_state_t *oldent, *newent;
  102. int oldindex, newindex;
  103. int oldnum, newnum;
  104. int from_num_entities;
  105. int bits;
  106. #if 0
  107. if (numprojs)
  108. MSG_WriteByte (msg, svc_packetentities2);
  109. else
  110. #endif
  111. MSG_WriteByte (msg, svc_packetentities);
  112. if (!from)
  113. from_num_entities = 0;
  114. else
  115. from_num_entities = from->num_entities;
  116. newindex = 0;
  117. oldindex = 0;
  118. while (newindex < to->num_entities || oldindex < from_num_entities)
  119. {
  120. if (newindex >= to->num_entities)
  121. newnum = 9999;
  122. else
  123. {
  124. newent = &svs.client_entities[(to->first_entity+newindex)%svs.num_client_entities];
  125. newnum = newent->number;
  126. }
  127. if (oldindex >= from_num_entities)
  128. oldnum = 9999;
  129. else
  130. {
  131. oldent = &svs.client_entities[(from->first_entity+oldindex)%svs.num_client_entities];
  132. oldnum = oldent->number;
  133. }
  134. if (newnum == oldnum)
  135. { // delta update from old position
  136. // because the force parm is false, this will not result
  137. // in any bytes being emited if the entity has not changed at all
  138. // note that players are always 'newentities', this updates their oldorigin always
  139. // and prevents warping
  140. MSG_WriteDeltaEntity (oldent, newent, msg, false, newent->number <= maxclients->value);
  141. oldindex++;
  142. newindex++;
  143. continue;
  144. }
  145. if (newnum < oldnum)
  146. { // this is a new entity, send it from the baseline
  147. MSG_WriteDeltaEntity (&sv.baselines[newnum], newent, msg, true, true);
  148. newindex++;
  149. continue;
  150. }
  151. if (newnum > oldnum)
  152. { // the old entity isn't present in the new message
  153. bits = U_REMOVE;
  154. if (oldnum >= 256)
  155. bits |= U_NUMBER16 | U_MOREBITS1;
  156. MSG_WriteByte (msg, bits&255 );
  157. if (bits & 0x0000ff00)
  158. MSG_WriteByte (msg, (bits>>8)&255 );
  159. if (bits & U_NUMBER16)
  160. MSG_WriteShort (msg, oldnum);
  161. else
  162. MSG_WriteByte (msg, oldnum);
  163. oldindex++;
  164. continue;
  165. }
  166. }
  167. MSG_WriteShort (msg, 0); // end of packetentities
  168. #if 0
  169. if (numprojs)
  170. SV_EmitProjectileUpdate(msg);
  171. #endif
  172. }
  173. /*
  174. =============
  175. SV_WritePlayerstateToClient
  176. =============
  177. */
  178. void SV_WritePlayerstateToClient (client_frame_t *from, client_frame_t *to, sizebuf_t *msg)
  179. {
  180. int i;
  181. int pflags;
  182. player_state_t *ps, *ops;
  183. player_state_t dummy;
  184. int statbits;
  185. ps = &to->ps;
  186. if (!from)
  187. {
  188. memset (&dummy, 0, sizeof(dummy));
  189. ops = &dummy;
  190. }
  191. else
  192. ops = &from->ps;
  193. //
  194. // determine what needs to be sent
  195. //
  196. pflags = 0;
  197. if (ps->pmove.pm_type != ops->pmove.pm_type)
  198. pflags |= PS_M_TYPE;
  199. if (ps->pmove.origin[0] != ops->pmove.origin[0]
  200. || ps->pmove.origin[1] != ops->pmove.origin[1]
  201. || ps->pmove.origin[2] != ops->pmove.origin[2] )
  202. pflags |= PS_M_ORIGIN;
  203. if (ps->pmove.velocity[0] != ops->pmove.velocity[0]
  204. || ps->pmove.velocity[1] != ops->pmove.velocity[1]
  205. || ps->pmove.velocity[2] != ops->pmove.velocity[2] )
  206. pflags |= PS_M_VELOCITY;
  207. if (ps->pmove.pm_time != ops->pmove.pm_time)
  208. pflags |= PS_M_TIME;
  209. if (ps->pmove.pm_flags != ops->pmove.pm_flags)
  210. pflags |= PS_M_FLAGS;
  211. if (ps->pmove.gravity != ops->pmove.gravity)
  212. pflags |= PS_M_GRAVITY;
  213. if (ps->pmove.delta_angles[0] != ops->pmove.delta_angles[0]
  214. || ps->pmove.delta_angles[1] != ops->pmove.delta_angles[1]
  215. || ps->pmove.delta_angles[2] != ops->pmove.delta_angles[2] )
  216. pflags |= PS_M_DELTA_ANGLES;
  217. if (ps->viewoffset[0] != ops->viewoffset[0]
  218. || ps->viewoffset[1] != ops->viewoffset[1]
  219. || ps->viewoffset[2] != ops->viewoffset[2] )
  220. pflags |= PS_VIEWOFFSET;
  221. if (ps->viewangles[0] != ops->viewangles[0]
  222. || ps->viewangles[1] != ops->viewangles[1]
  223. || ps->viewangles[2] != ops->viewangles[2] )
  224. pflags |= PS_VIEWANGLES;
  225. if (ps->kick_angles[0] != ops->kick_angles[0]
  226. || ps->kick_angles[1] != ops->kick_angles[1]
  227. || ps->kick_angles[2] != ops->kick_angles[2] )
  228. pflags |= PS_KICKANGLES;
  229. if (ps->blend[0] != ops->blend[0]
  230. || ps->blend[1] != ops->blend[1]
  231. || ps->blend[2] != ops->blend[2]
  232. || ps->blend[3] != ops->blend[3] )
  233. pflags |= PS_BLEND;
  234. if (ps->fov != ops->fov)
  235. pflags |= PS_FOV;
  236. if (ps->rdflags != ops->rdflags)
  237. pflags |= PS_RDFLAGS;
  238. if (ps->gunframe != ops->gunframe)
  239. pflags |= PS_WEAPONFRAME;
  240. pflags |= PS_WEAPONINDEX;
  241. //
  242. // write it
  243. //
  244. MSG_WriteByte (msg, svc_playerinfo);
  245. MSG_WriteShort (msg, pflags);
  246. //
  247. // write the pmove_state_t
  248. //
  249. if (pflags & PS_M_TYPE)
  250. MSG_WriteByte (msg, ps->pmove.pm_type);
  251. if (pflags & PS_M_ORIGIN)
  252. {
  253. MSG_WriteShort (msg, ps->pmove.origin[0]);
  254. MSG_WriteShort (msg, ps->pmove.origin[1]);
  255. MSG_WriteShort (msg, ps->pmove.origin[2]);
  256. }
  257. if (pflags & PS_M_VELOCITY)
  258. {
  259. MSG_WriteShort (msg, ps->pmove.velocity[0]);
  260. MSG_WriteShort (msg, ps->pmove.velocity[1]);
  261. MSG_WriteShort (msg, ps->pmove.velocity[2]);
  262. }
  263. if (pflags & PS_M_TIME)
  264. MSG_WriteByte (msg, ps->pmove.pm_time);
  265. if (pflags & PS_M_FLAGS)
  266. MSG_WriteByte (msg, ps->pmove.pm_flags);
  267. if (pflags & PS_M_GRAVITY)
  268. MSG_WriteShort (msg, ps->pmove.gravity);
  269. if (pflags & PS_M_DELTA_ANGLES)
  270. {
  271. MSG_WriteShort (msg, ps->pmove.delta_angles[0]);
  272. MSG_WriteShort (msg, ps->pmove.delta_angles[1]);
  273. MSG_WriteShort (msg, ps->pmove.delta_angles[2]);
  274. }
  275. //
  276. // write the rest of the player_state_t
  277. //
  278. if (pflags & PS_VIEWOFFSET)
  279. {
  280. MSG_WriteChar (msg, ps->viewoffset[0]*4);
  281. MSG_WriteChar (msg, ps->viewoffset[1]*4);
  282. MSG_WriteChar (msg, ps->viewoffset[2]*4);
  283. }
  284. if (pflags & PS_VIEWANGLES)
  285. {
  286. MSG_WriteAngle16 (msg, ps->viewangles[0]);
  287. MSG_WriteAngle16 (msg, ps->viewangles[1]);
  288. MSG_WriteAngle16 (msg, ps->viewangles[2]);
  289. }
  290. if (pflags & PS_KICKANGLES)
  291. {
  292. MSG_WriteChar (msg, ps->kick_angles[0]*4);
  293. MSG_WriteChar (msg, ps->kick_angles[1]*4);
  294. MSG_WriteChar (msg, ps->kick_angles[2]*4);
  295. }
  296. if (pflags & PS_WEAPONINDEX)
  297. {
  298. MSG_WriteByte (msg, ps->gunindex);
  299. }
  300. if (pflags & PS_WEAPONFRAME)
  301. {
  302. MSG_WriteByte (msg, ps->gunframe);
  303. MSG_WriteChar (msg, ps->gunoffset[0]*4);
  304. MSG_WriteChar (msg, ps->gunoffset[1]*4);
  305. MSG_WriteChar (msg, ps->gunoffset[2]*4);
  306. MSG_WriteChar (msg, ps->gunangles[0]*4);
  307. MSG_WriteChar (msg, ps->gunangles[1]*4);
  308. MSG_WriteChar (msg, ps->gunangles[2]*4);
  309. }
  310. if (pflags & PS_BLEND)
  311. {
  312. MSG_WriteByte (msg, ps->blend[0]*255);
  313. MSG_WriteByte (msg, ps->blend[1]*255);
  314. MSG_WriteByte (msg, ps->blend[2]*255);
  315. MSG_WriteByte (msg, ps->blend[3]*255);
  316. }
  317. if (pflags & PS_FOV)
  318. MSG_WriteByte (msg, ps->fov);
  319. if (pflags & PS_RDFLAGS)
  320. MSG_WriteByte (msg, ps->rdflags);
  321. // send stats
  322. statbits = 0;
  323. for (i=0 ; i<MAX_STATS ; i++)
  324. if (ps->stats[i] != ops->stats[i])
  325. statbits |= 1<<i;
  326. MSG_WriteLong (msg, statbits);
  327. for (i=0 ; i<MAX_STATS ; i++)
  328. if (statbits & (1<<i) )
  329. MSG_WriteShort (msg, ps->stats[i]);
  330. }
  331. /*
  332. ==================
  333. SV_WriteFrameToClient
  334. ==================
  335. */
  336. void SV_WriteFrameToClient (client_t *client, sizebuf_t *msg)
  337. {
  338. client_frame_t *frame, *oldframe;
  339. int lastframe;
  340. //Com_Printf ("%i -> %i\n", client->lastframe, sv.framenum);
  341. // this is the frame we are creating
  342. frame = &client->frames[sv.framenum & UPDATE_MASK];
  343. if (client->lastframe <= 0)
  344. { // client is asking for a retransmit
  345. oldframe = NULL;
  346. lastframe = -1;
  347. }
  348. else if (sv.framenum - client->lastframe >= (UPDATE_BACKUP - 3) )
  349. { // client hasn't gotten a good message through in a long time
  350. // Com_Printf ("%s: Delta request from out-of-date packet.\n", client->name);
  351. oldframe = NULL;
  352. lastframe = -1;
  353. }
  354. else
  355. { // we have a valid message to delta from
  356. oldframe = &client->frames[client->lastframe & UPDATE_MASK];
  357. lastframe = client->lastframe;
  358. }
  359. MSG_WriteByte (msg, svc_frame);
  360. MSG_WriteLong (msg, sv.framenum);
  361. MSG_WriteLong (msg, lastframe); // what we are delta'ing from
  362. MSG_WriteByte (msg, client->surpressCount); // rate dropped packets
  363. client->surpressCount = 0;
  364. // send over the areabits
  365. MSG_WriteByte (msg, frame->areabytes);
  366. SZ_Write (msg, frame->areabits, frame->areabytes);
  367. // delta encode the playerstate
  368. SV_WritePlayerstateToClient (oldframe, frame, msg);
  369. // delta encode the entities
  370. SV_EmitPacketEntities (oldframe, frame, msg);
  371. }
  372. /*
  373. =============================================================================
  374. Build a client frame structure
  375. =============================================================================
  376. */
  377. byte fatpvs[65536/8]; // 32767 is MAX_MAP_LEAFS
  378. /*
  379. ============
  380. SV_FatPVS
  381. The client will interpolate the view position,
  382. so we can't use a single PVS point
  383. ===========
  384. */
  385. void SV_FatPVS (vec3_t org)
  386. {
  387. int leafs[64];
  388. int i, j, count;
  389. int longs;
  390. byte *src;
  391. vec3_t mins, maxs;
  392. for (i=0 ; i<3 ; i++)
  393. {
  394. mins[i] = org[i] - 8;
  395. maxs[i] = org[i] + 8;
  396. }
  397. count = CM_BoxLeafnums (mins, maxs, leafs, 64, NULL);
  398. if (count < 1)
  399. Com_Error (ERR_FATAL, "SV_FatPVS: count < 1");
  400. longs = (CM_NumClusters()+31)>>5;
  401. // convert leafs to clusters
  402. for (i=0 ; i<count ; i++)
  403. leafs[i] = CM_LeafCluster(leafs[i]);
  404. memcpy (fatpvs, CM_ClusterPVS(leafs[0]), longs<<2);
  405. // or in all the other leaf bits
  406. for (i=1 ; i<count ; i++)
  407. {
  408. for (j=0 ; j<i ; j++)
  409. if (leafs[i] == leafs[j])
  410. break;
  411. if (j != i)
  412. continue; // already have the cluster we want
  413. src = CM_ClusterPVS(leafs[i]);
  414. for (j=0 ; j<longs ; j++)
  415. ((long *)fatpvs)[j] |= ((long *)src)[j];
  416. }
  417. }
  418. /*
  419. =============
  420. SV_BuildClientFrame
  421. Decides which entities are going to be visible to the client, and
  422. copies off the playerstat and areabits.
  423. =============
  424. */
  425. void SV_BuildClientFrame (client_t *client)
  426. {
  427. int e, i;
  428. vec3_t org;
  429. edict_t *ent;
  430. edict_t *clent;
  431. client_frame_t *frame;
  432. entity_state_t *state;
  433. int l;
  434. int clientarea, clientcluster;
  435. int leafnum;
  436. int c_fullsend;
  437. byte *clientphs;
  438. byte *bitvector;
  439. clent = client->edict;
  440. if (!clent->client)
  441. return; // not in game yet
  442. #if 0
  443. numprojs = 0; // no projectiles yet
  444. #endif
  445. // this is the frame we are creating
  446. frame = &client->frames[sv.framenum & UPDATE_MASK];
  447. frame->senttime = svs.realtime; // save it for ping calc later
  448. // find the client's PVS
  449. for (i=0 ; i<3 ; i++)
  450. org[i] = clent->client->ps.pmove.origin[i]*0.125 + clent->client->ps.viewoffset[i];
  451. leafnum = CM_PointLeafnum (org);
  452. clientarea = CM_LeafArea (leafnum);
  453. clientcluster = CM_LeafCluster (leafnum);
  454. // calculate the visible areas
  455. frame->areabytes = CM_WriteAreaBits (frame->areabits, clientarea);
  456. // grab the current player_state_t
  457. frame->ps = clent->client->ps;
  458. SV_FatPVS (org);
  459. clientphs = CM_ClusterPHS (clientcluster);
  460. // build up the list of visible entities
  461. frame->num_entities = 0;
  462. frame->first_entity = svs.next_client_entities;
  463. c_fullsend = 0;
  464. for (e=1 ; e<ge->num_edicts ; e++)
  465. {
  466. ent = EDICT_NUM(e);
  467. // ignore ents without visible models
  468. if (ent->svflags & SVF_NOCLIENT)
  469. continue;
  470. // ignore ents without visible models unless they have an effect
  471. if (!ent->s.modelindex && !ent->s.effects && !ent->s.sound
  472. && !ent->s.event)
  473. continue;
  474. // ignore if not touching a PV leaf
  475. if (ent != clent)
  476. {
  477. // check area
  478. if (!CM_AreasConnected (clientarea, ent->areanum))
  479. { // doors can legally straddle two areas, so
  480. // we may need to check another one
  481. if (!ent->areanum2
  482. || !CM_AreasConnected (clientarea, ent->areanum2))
  483. continue; // blocked by a door
  484. }
  485. // beams just check one point for PHS
  486. if (ent->s.renderfx & RF_BEAM)
  487. {
  488. l = ent->clusternums[0];
  489. if ( !(clientphs[l >> 3] & (1 << (l&7) )) )
  490. continue;
  491. }
  492. else
  493. {
  494. // FIXME: if an ent has a model and a sound, but isn't
  495. // in the PVS, only the PHS, clear the model
  496. if (ent->s.sound)
  497. {
  498. bitvector = fatpvs; //clientphs;
  499. }
  500. else
  501. bitvector = fatpvs;
  502. if (ent->num_clusters == -1)
  503. { // too many leafs for individual check, go by headnode
  504. if (!CM_HeadnodeVisible (ent->headnode, bitvector))
  505. continue;
  506. c_fullsend++;
  507. }
  508. else
  509. { // check individual leafs
  510. for (i=0 ; i < ent->num_clusters ; i++)
  511. {
  512. l = ent->clusternums[i];
  513. if (bitvector[l >> 3] & (1 << (l&7) ))
  514. break;
  515. }
  516. if (i == ent->num_clusters)
  517. continue; // not visible
  518. }
  519. if (!ent->s.modelindex)
  520. { // don't send sounds if they will be attenuated away
  521. vec3_t delta;
  522. float len;
  523. VectorSubtract (org, ent->s.origin, delta);
  524. len = VectorLength (delta);
  525. if (len > 400)
  526. continue;
  527. }
  528. }
  529. }
  530. #if 0
  531. if (SV_AddProjectileUpdate(ent))
  532. continue; // added as a special projectile
  533. #endif
  534. // add it to the circular client_entities array
  535. state = &svs.client_entities[svs.next_client_entities%svs.num_client_entities];
  536. if (ent->s.number != e)
  537. {
  538. Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
  539. ent->s.number = e;
  540. }
  541. *state = ent->s;
  542. // don't mark players missiles as solid
  543. if (ent->owner == client->edict)
  544. state->solid = 0;
  545. svs.next_client_entities++;
  546. frame->num_entities++;
  547. }
  548. }
  549. /*
  550. ==================
  551. SV_RecordDemoMessage
  552. Save everything in the world out without deltas.
  553. Used for recording footage for merged or assembled demos
  554. ==================
  555. */
  556. void SV_RecordDemoMessage (void)
  557. {
  558. int e;
  559. edict_t *ent;
  560. entity_state_t nostate;
  561. sizebuf_t buf;
  562. byte buf_data[32768];
  563. int len;
  564. if (!svs.demofile)
  565. return;
  566. memset (&nostate, 0, sizeof(nostate));
  567. SZ_Init (&buf, buf_data, sizeof(buf_data));
  568. // write a frame message that doesn't contain a player_state_t
  569. MSG_WriteByte (&buf, svc_frame);
  570. MSG_WriteLong (&buf, sv.framenum);
  571. MSG_WriteByte (&buf, svc_packetentities);
  572. e = 1;
  573. ent = EDICT_NUM(e);
  574. while (e < ge->num_edicts)
  575. {
  576. // ignore ents without visible models unless they have an effect
  577. if (ent->inuse &&
  578. ent->s.number &&
  579. (ent->s.modelindex || ent->s.effects || ent->s.sound || ent->s.event) &&
  580. !(ent->svflags & SVF_NOCLIENT))
  581. MSG_WriteDeltaEntity (&nostate, &ent->s, &buf, false, true);
  582. e++;
  583. ent = EDICT_NUM(e);
  584. }
  585. MSG_WriteShort (&buf, 0); // end of packetentities
  586. // now add the accumulated multicast information
  587. SZ_Write (&buf, svs.demo_multicast.data, svs.demo_multicast.cursize);
  588. SZ_Clear (&svs.demo_multicast);
  589. // now write the entire message to the file, prefixed by the length
  590. len = LittleLong (buf.cursize);
  591. fwrite (&len, 4, 1, svs.demofile);
  592. fwrite (buf.data, buf.cursize, 1, svs.demofile);
  593. }