Quake II RTX doxygen  1.0 dev
demo.c File Reference
#include "client.h"

Go to the source code of this file.

Classes

struct  demosnap_t
 

Macros

#define FRAME_PRE   (cls.demo.frames_written)
 
#define FRAME_CUR   (cls.demo.frames_written + 1)
 

Functions

qboolean CL_WriteDemoMessage (sizebuf_t *buf)
 
static void emit_packet_entities (server_frame_t *from, server_frame_t *to)
 
static void emit_delta_frame (server_frame_t *from, server_frame_t *to, int fromnum, int tonum)
 
void CL_EmitDemoFrame (void)
 
static size_t format_demo_size (char *buffer, size_t size)
 
static size_t format_demo_status (char *buffer, size_t size)
 
void CL_Stop_f (void)
 
static void CL_Record_f (void)
 
static void resume_record (void)
 
static void CL_Suspend_f (void)
 
static int read_first_message (qhandle_t f)
 
static int read_next_message (qhandle_t f)
 
static void finish_demo (int ret)
 
static void update_status (void)
 
static int parse_next_message (int wait)
 
static void CL_PlayDemo_f (void)
 
static void CL_Demo_c (genctx_t *ctx, int argnum)
 
void CL_EmitDemoSnapshot (void)
 
static demosnap_tfind_snapshot (int framenum)
 
void CL_FirstDemoFrame (void)
 
static void CL_Seek_f (void)
 
static void parse_info_string (demoInfo_t *info, int clientNum, int index, const char *string)
 
demoInfo_t * CL_GetDemoInfo (const char *path, demoInfo_t *info)
 
void CL_CleanupDemos (void)
 
void CL_DemoFrame (int msec)
 
void CL_InitDemos (void)
 

Variables

static byte demo_buffer [MAX_PACKETLEN]
 
static cvar_t * cl_demosnaps
 
static cvar_t * cl_demomsglen
 
static cvar_t * cl_demowait
 
static const cmd_option_t o_record []
 
static const cmdreg_t c_demo []
 

Macro Definition Documentation

◆ FRAME_CUR

#define FRAME_CUR   (cls.demo.frames_written + 1)

Definition at line 177 of file demo.c.

◆ FRAME_PRE

#define FRAME_PRE   (cls.demo.frames_written)

Definition at line 176 of file demo.c.

Function Documentation

◆ CL_CleanupDemos()

void CL_CleanupDemos ( void  )

Definition at line 1179 of file demo.c.

1180 {
1181  demosnap_t *snap, *next;
1182  size_t total;
1183 
1184  if (cls.demo.recording) {
1185  CL_Stop_f();
1186  }
1187 
1188  if (cls.demo.playback) {
1190 
1191  if (com_timedemo->integer && cls.demo.time_frames) {
1192  unsigned msec = Sys_Milliseconds();
1193 
1194  if (msec > cls.demo.time_start) {
1195  float sec = (msec - cls.demo.time_start) * 0.001f;
1196  float fps = cls.demo.time_frames / sec;
1197 
1198  Com_Printf("%u frames, %3.1f seconds: %3.1f fps\n",
1199  cls.demo.time_frames, sec, fps);
1200  }
1201  }
1202  }
1203 
1204  total = 0;
1205  LIST_FOR_EACH_SAFE(demosnap_t, snap, next, &cls.demo.snapshots, entry) {
1206  total += snap->msglen;
1207  Z_Free(snap);
1208  }
1209 
1210  if (total)
1211  Com_DPrintf("Freed %"PRIz" bytes of snaps\n", total);
1212 
1213  memset(&cls.demo, 0, sizeof(cls.demo));
1214 
1215  List_Init(&cls.demo.snapshots);
1216 }

Referenced by CL_Disconnect().

◆ CL_Demo_c()

static void CL_Demo_c ( genctx_t *  ctx,
int  argnum 
)
static

Definition at line 750 of file demo.c.

751 {
752  if (argnum == 1) {
753  FS_File_g("demos", "*.dm2;*.dm2.gz;*.mvd2;*.mvd2.gz", FS_SEARCH_SAVEPATH | FS_SEARCH_BYFILTER, ctx);
754  }
755 }

◆ CL_DemoFrame()

void CL_DemoFrame ( int  msec)

Definition at line 1223 of file demo.c.

1224 {
1225  if (cls.state < ca_connected) {
1226  return;
1227  }
1228 
1229  if (cls.state != ca_active) {
1230  parse_next_message(0);
1231  return;
1232  }
1233 
1234  if (com_timedemo->integer) {
1235  parse_next_message(0);
1236  cl.time = cl.servertime;
1237  cls.demo.time_frames++;
1238  return;
1239  }
1240 
1241  // wait at the end of demo
1242  if (cls.demo.eof) {
1243  if (!cl_demowait->integer)
1244  finish_demo(0);
1245  return;
1246  }
1247 
1248  // cl.time has already been advanced for this client frame
1249  // read the next frame to start lerp cycle again
1250  while (cl.servertime < cl.time) {
1251  if (parse_next_message(cl_demowait->integer))
1252  break;
1253  if (cls.state != ca_active)
1254  break;
1255  }
1256 }

Referenced by CL_Frame().

◆ CL_EmitDemoFrame()

void CL_EmitDemoFrame ( void  )

Definition at line 186 of file demo.c.

187 {
188  server_frame_t *oldframe;
189  int lastframe;
190 
191  if (!cl.frame.valid)
192  return;
193 
194  // the first frame is delta uncompressed
195  if (cls.demo.last_server_frame == -1) {
196  oldframe = NULL;
197  lastframe = -1;
198  } else {
199  oldframe = &cl.frames[cls.demo.last_server_frame & UPDATE_MASK];
200  lastframe = FRAME_PRE;
201  if (oldframe->number != cls.demo.last_server_frame || !oldframe->valid ||
202  cl.numEntityStates - oldframe->firstEntity > MAX_PARSE_ENTITIES) {
203  oldframe = NULL;
204  lastframe = -1;
205  }
206  }
207 
208  // emit and flush frame
209  emit_delta_frame(oldframe, &cl.frame, lastframe, FRAME_CUR);
210 
211  if (cls.demo.buffer.cursize + msg_write.cursize > cls.demo.buffer.maxsize) {
212  Com_DPrintf("Demo frame overflowed (%"PRIz" + %"PRIz" > %"PRIz")\n",
213  cls.demo.buffer.cursize, msg_write.cursize, cls.demo.buffer.maxsize);
215 
216  // warn the user if drop rate is too high
217  if (cls.demo.frames_written < 10 && cls.demo.frames_dropped == 50)
218  Com_WPrintf("Too many demo frames don't fit into %"PRIz" bytes.\n"
219  "Try to increase 'cl_demomsglen' value and restart recording.\n",
220  cls.demo.buffer.maxsize);
221  } else {
222  SZ_Write(&cls.demo.buffer, msg_write.data, msg_write.cursize);
225  }
226 
228 }

Referenced by CL_DeltaFrame(), and resume_record().

◆ CL_EmitDemoSnapshot()

void CL_EmitDemoSnapshot ( void  )

Definition at line 773 of file demo.c.

774 {
775  demosnap_t *snap;
776  off_t pos;
777  char *from, *to;
778  size_t len;
779  server_frame_t *lastframe, *frame;
780  int i, j, lastnum;
781 
782  if (cl_demosnaps->integer <= 0)
783  return;
784 
785  if (cls.demo.frames_read < cls.demo.last_snapshot + cl_demosnaps->integer * 10)
786  return;
787 
788  if (!cl.frame.valid)
789  return;
790 
791  if (!cls.demo.file_size)
792  return;
793 
794  pos = FS_Tell(cls.demo.playback);
795  if (pos < cls.demo.file_offset)
796  return;
797 
798  // write all the backups, since we can't predict what frame the next
799  // delta will come from
800  lastframe = NULL;
801  lastnum = -1;
802  for (i = 0; i < UPDATE_BACKUP; i++) {
803  j = cl.frame.number - (UPDATE_BACKUP - 1) + i;
804  frame = &cl.frames[j & UPDATE_MASK];
805  if (frame->number != j || !frame->valid ||
806  cl.numEntityStates - frame->firstEntity > MAX_PARSE_ENTITIES) {
807  continue;
808  }
809 
810  emit_delta_frame(lastframe, frame, lastnum, j);
811  lastframe = frame;
812  lastnum = frame->number;
813  }
814 
815  // write configstrings
816  for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
817  from = cl.baseconfigstrings[i];
818  to = cl.configstrings[i];
819 
820  if (!strcmp(from, to))
821  continue;
822 
823  len = strlen(to);
824  if (len > MAX_QPATH)
825  len = MAX_QPATH;
826 
827  MSG_WriteByte(svc_configstring);
828  MSG_WriteShort(i);
829  MSG_WriteData(to, len);
830  MSG_WriteByte(0);
831  }
832 
833  // write layout
836 
837  snap = Z_Malloc(sizeof(*snap) + msg_write.cursize - 1);
838  snap->framenum = cls.demo.frames_read;
839  snap->filepos = pos;
840  snap->msglen = msg_write.cursize;
841  memcpy(snap->data, msg_write.data, msg_write.cursize);
842  List_Append(&cls.demo.snapshots, &snap->entry);
843 
844  Com_DPrintf("[%d] snaplen %"PRIz"\n", cls.demo.frames_read, msg_write.cursize);
845 
847 
849 }

Referenced by CL_Seek_f(), and parse_next_message().

◆ CL_FirstDemoFrame()

void CL_FirstDemoFrame ( void  )

Definition at line 876 of file demo.c.

877 {
878  ssize_t len, ofs;
879 
880  Com_DPrintf("[%d] first frame\n", cl.frame.number);
881 
882  // save base configstrings
884 
885  // obtain file length and offset of the second frame
886  len = FS_Length(cls.demo.playback);
887  ofs = FS_Tell(cls.demo.playback);
888  if (len > 0 && ofs > 0) {
889  cls.demo.file_offset = ofs;
890  cls.demo.file_size = len - ofs;
891  }
892 
893  // begin timedemo
894  if (com_timedemo->integer) {
895  cls.demo.time_frames = 0;
897  }
898 
899  // force initial snapshot
900  cls.demo.last_snapshot = INT_MIN;
901 }

Referenced by set_active_state().

◆ CL_GetDemoInfo()

demoInfo_t* CL_GetDemoInfo ( const char *  path,
demoInfo_t *  info 
)

Definition at line 1091 of file demo.c.

1092 {
1093  qhandle_t f;
1094  int c, index;
1095  char string[MAX_QPATH];
1096  int clientNum, type;
1097 
1098  FS_FOpenFile(path, &f, FS_MODE_READ);
1099  if (!f) {
1100  return NULL;
1101  }
1102 
1103  type = read_first_message(f);
1104  if (type < 0) {
1105  goto fail;
1106  }
1107 
1108  if (type == 0) {
1109  if (MSG_ReadByte() != svc_serverdata) {
1110  goto fail;
1111  }
1112  if (MSG_ReadLong() != PROTOCOL_VERSION_DEFAULT) {
1113  goto fail;
1114  }
1115  MSG_ReadLong();
1116  MSG_ReadByte();
1117  MSG_ReadString(NULL, 0);
1118  clientNum = MSG_ReadShort();
1119  MSG_ReadString(NULL, 0);
1120 
1121  while (1) {
1122  c = MSG_ReadByte();
1123  if (c == -1) {
1124  if (read_next_message(f) <= 0) {
1125  break;
1126  }
1127  continue; // parse new message
1128  }
1129  if (c != svc_configstring) {
1130  break;
1131  }
1132  index = MSG_ReadShort();
1133  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
1134  goto fail;
1135  }
1136  MSG_ReadString(string, sizeof(string));
1137  parse_info_string(info, clientNum, index, string);
1138  }
1139 
1140  info->mvd = qfalse;
1141  } else {
1142  if ((MSG_ReadByte() & SVCMD_MASK) != mvd_serverdata) {
1143  goto fail;
1144  }
1145  if (MSG_ReadLong() != PROTOCOL_VERSION_MVD) {
1146  goto fail;
1147  }
1148  MSG_ReadShort();
1149  MSG_ReadLong();
1150  MSG_ReadString(NULL, 0);
1151  clientNum = MSG_ReadShort();
1152 
1153  while (1) {
1154  index = MSG_ReadShort();
1155  if (index == MAX_CONFIGSTRINGS) {
1156  break;
1157  }
1158  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
1159  goto fail;
1160  }
1161  MSG_ReadString(string, sizeof(string));
1162  parse_info_string(info, clientNum, index, string);
1163  }
1164 
1165  info->mvd = qtrue;
1166  }
1167 
1168  FS_FCloseFile(f);
1169  return info;
1170 
1171 fail:
1172  FS_FCloseFile(f);
1173  return NULL;
1174 
1175 }

Referenced by BuildName().

◆ CL_InitDemos()

void CL_InitDemos ( void  )

Definition at line 1273 of file demo.c.

1274 {
1275  cl_demosnaps = Cvar_Get("cl_demosnaps", "10", 0);
1276  cl_demomsglen = Cvar_Get("cl_demomsglen", va("%d", MAX_PACKETLEN_WRITABLE_DEFAULT), 0);
1277  cl_demowait = Cvar_Get("cl_demowait", "0", 0);
1278 
1280  List_Init(&cls.demo.snapshots);
1281 }

Referenced by CL_InitLocal().

◆ CL_PlayDemo_f()

static void CL_PlayDemo_f ( void  )
static

Definition at line 693 of file demo.c.

694 {
695  char name[MAX_OSPATH];
696  qhandle_t f;
697  int type;
698 
699  if (Cmd_Argc() < 2) {
700  Com_Printf("Usage: %s <filename>\n", Cmd_Argv(0));
701  return;
702  }
703 
704  f = FS_EasyOpenFile(name, sizeof(name), FS_MODE_READ,
705  "demos/", Cmd_Argv(1), ".dm2");
706  if (!f) {
707  return;
708  }
709 
710  type = read_first_message(f);
711  if (type < 0) {
712  Com_Printf("Couldn't read %s: %s\n", name, Q_ErrorString(type));
713  FS_FCloseFile(f);
714  return;
715  }
716 
717  if (type == 1) {
718 #if USE_MVD_CLIENT
719  Cbuf_InsertText(&cmd_buffer, va("mvdplay --replace @@ \"/%s\"\n", name));
720 #else
721  Com_Printf("MVD support was not compiled in.\n");
722 #endif
723  FS_FCloseFile(f);
724  return;
725  }
726 
727  // if running a local server, kill it and reissue
728  SV_Shutdown("Server was killed.\n", ERR_DISCONNECT);
729 
730  CL_Disconnect(ERR_RECONNECT);
731 
732  cls.demo.playback = f;
735  cls.serverAddress.type = NA_LOOPBACK;
736 
737  Con_Popup(qtrue);
739 
740  // parse the first message just read
742 
743  // read and parse messages util `precache' command
744  while (cls.state == ca_connected) {
747  }
748 }

◆ CL_Record_f()

static void CL_Record_f ( void  )
static

Definition at line 316 of file demo.c.

317 {
318  char buffer[MAX_OSPATH];
319  int i, c;
320  size_t len;
321  entity_state_t *ent;
322  entity_packed_t pack;
323  char *s;
324  qhandle_t f;
325  unsigned mode = FS_MODE_WRITE;
326  size_t size = Cvar_ClampInteger(
328  MIN_PACKETLEN,
329  MAX_PACKETLEN_WRITABLE);
330 
331  while ((c = Cmd_ParseOptions(o_record)) != -1) {
332  switch (c) {
333  case 'h':
334  Cmd_PrintUsage(o_record, "<filename>");
335  Com_Printf("Begin client demo recording.\n");
337  return;
338  case 'z':
339  mode |= FS_FLAG_GZIP;
340  case 'e':
341  size = MAX_PACKETLEN_WRITABLE;
342  break;
343  case 's':
344  size = MAX_PACKETLEN_WRITABLE_DEFAULT;
345  break;
346  default:
347  return;
348  }
349  }
350 
351  if (cls.demo.recording) {
352  format_demo_status(buffer, sizeof(buffer));
353  Com_Printf("Already recording (%s).\n", buffer);
354  return;
355  }
356 
357  if (!cmd_optarg[0]) {
358  Com_Printf("Missing filename argument.\n");
359  Cmd_PrintHint();
360  return;
361  }
362 
363  if (cls.state != ca_active) {
364  Com_Printf("You must be in a level to record.\n");
365  return;
366  }
367 
368  //
369  // open the demo file
370  //
371  f = FS_EasyOpenFile(buffer, sizeof(buffer), mode,
372  "demos/", cmd_optarg, ".dm2");
373  if (!f) {
374  return;
375  }
376 
377  Com_Printf("Recording client demo to %s.\n", buffer);
378 
379  cls.demo.recording = f;
380  cls.demo.paused = qfalse;
381 
382  // the first frame will be delta uncompressed
384 
385  SZ_Init(&cls.demo.buffer, demo_buffer, size);
386 
387  // clear dirty configstrings
388  memset(cl.dcs, 0, sizeof(cl.dcs));
389 
390  // tell the server we are recording
392 
393  //
394  // write out messages to hold the startup information
395  //
396 
397  // send the serverdata
398  MSG_WriteByte(svc_serverdata);
399  MSG_WriteLong(PROTOCOL_VERSION_DEFAULT);
400  MSG_WriteLong(0x10000 + cl.servercount);
401  MSG_WriteByte(1); // demos are always attract loops
404  MSG_WriteString(cl.configstrings[CS_NAME]);
405 
406  // configstrings
407  for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
408  s = cl.configstrings[i];
409  if (!*s)
410  continue;
411 
412  len = strlen(s);
413  if (len > MAX_QPATH)
414  len = MAX_QPATH;
415 
416  if (msg_write.cursize + len + 4 > size) {
418  return;
419  }
420 
421  MSG_WriteByte(svc_configstring);
422  MSG_WriteShort(i);
423  MSG_WriteData(s, len);
424  MSG_WriteByte(0);
425  }
426 
427  // baselines
428  for (i = 1; i < MAX_EDICTS; i++) {
429  ent = &cl.baselines[i];
430  if (!ent->number)
431  continue;
432 
433  if (msg_write.cursize + 64 > size) {
435  return;
436  }
437 
438  MSG_WriteByte(svc_spawnbaseline);
439  MSG_PackEntity(&pack, ent, qfalse);
440  MSG_WriteDeltaEntity(NULL, &pack, MSG_ES_FORCE);
441  }
442 
444  MSG_WriteString("precache\n");
445 
446  // write it to the demo file
448 
449  // the rest of the demo file will be individual frames
450 }

◆ CL_Seek_f()

static void CL_Seek_f ( void  )
static

Definition at line 903 of file demo.c.

904 {
905  demosnap_t *snap;
906  int i, j, ret, index, frames, dest, prev;
907  char *from, *to;
908 
909  if (Cmd_Argc() < 2) {
910  Com_Printf("Usage: %s [+-]<timespec>\n", Cmd_Argv(0));
911  return;
912  }
913 
914 #if USE_MVD_CLIENT
915  if (sv_running->integer == ss_broadcast) {
916  Cbuf_InsertText(&cmd_buffer, va("mvdseek \"%s\" @@\n", Cmd_Argv(1)));
917  return;
918  }
919 #endif
920 
921  if (!cls.demo.playback) {
922  Com_Printf("Not playing a demo.\n");
923  return;
924  }
925 
926  to = Cmd_Argv(1);
927 
928  if (*to == '-' || *to == '+') {
929  // relative to current frame
930  if (!Com_ParseTimespec(to + 1, &frames)) {
931  Com_Printf("Invalid relative timespec.\n");
932  return;
933  }
934  if (*to == '-')
935  frames = -frames;
936  dest = cls.demo.frames_read + frames;
937  } else {
938  // relative to first frame
939  if (!Com_ParseTimespec(to, &dest)) {
940  Com_Printf("Invalid absolute timespec.\n");
941  return;
942  }
943  frames = dest - cls.demo.frames_read;
944  }
945 
946  if (!frames)
947  // already there
948  return;
949 
950  if (frames > 0 && cls.demo.eof && cl_demowait->integer)
951  // already at end
952  return;
953 
954  // disable effects processing
955  cls.demo.seeking = qtrue;
956 
957  // clear dirty configstrings
958  memset(cl.dcs, 0, sizeof(cl.dcs));
959 
960  // stop sounds
961  S_StopAllSounds();
962 
963  // save previous server frame number
964  prev = cl.frame.number;
965 
966  Com_DPrintf("[%d] seeking to %d\n", cls.demo.frames_read, dest);
967 
968  // seek to the previous most recent snapshot
969  if (frames < 0 || cls.demo.last_snapshot > cls.demo.frames_read) {
970  snap = find_snapshot(dest);
971 
972  if (snap) {
973  Com_DPrintf("found snap at %d\n", snap->framenum);
974  ret = FS_Seek(cls.demo.playback, snap->filepos);
975  if (ret < 0) {
976  Com_EPrintf("Couldn't seek demo: %s\n", Q_ErrorString(ret));
977  goto done;
978  }
979 
980  // clear end-of-file flag
981  cls.demo.eof = qfalse;
982 
983  // reset configstrings
984  for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
985  from = cl.baseconfigstrings[i];
986  to = cl.configstrings[i];
987 
988  if (!strcmp(from, to))
989  continue;
990 
991  Q_SetBit(cl.dcs, i);
992  strcpy(to, from);
993  }
994 
995  SZ_Init(&msg_read, snap->data, snap->msglen);
996  msg_read.cursize = snap->msglen;
997 
999  cls.demo.frames_read = snap->framenum;
1000  Com_DPrintf("[%d] after snap parse %d\n", cls.demo.frames_read, cl.frame.number);
1001  } else if (frames < 0) {
1002  Com_Printf("Couldn't seek backwards without snapshots!\n");
1003  goto done;
1004  }
1005  }
1006 
1007  // skip forward to destination frame
1008  while (cls.demo.frames_read < dest) {
1010  if (ret == 0 && cl_demowait->integer) {
1011  cls.demo.eof = qtrue;
1012  break;
1013  }
1014  if (ret <= 0) {
1015  finish_demo(ret);
1016  return;
1017  }
1018 
1021  }
1022 
1023  Com_DPrintf("[%d] after skip %d\n", cls.demo.frames_read, cl.frame.number);
1024 
1025  // update dirty configstrings
1026  for (i = 0; i < CS_BITMAP_LONGS; i++) {
1027  if (((uint32_t *)cl.dcs)[i] == 0)
1028  continue;
1029 
1030  index = i << 5;
1031  for (j = 0; j < 32; j++, index++) {
1032  if (Q_IsBitSet(cl.dcs, index))
1033  CL_UpdateConfigstring(index);
1034  }
1035  }
1036 
1037  // don't lerp to old
1038  memset(&cl.oldframe, 0, sizeof(cl.oldframe));
1039 #if USE_FPS
1040  memset(&cl.oldkeyframe, 0, sizeof(cl.oldkeyframe));
1041 #endif
1042 
1043  // clear old effects
1044  CL_ClearEffects();
1045  CL_ClearTEnts();
1046 
1047  // fix time delta
1048  cl.serverdelta += cl.frame.number - prev;
1049 
1050  // fire up destination frame
1051  CL_DeltaFrame();
1052 
1053  if (cls.demo.recording && !cls.demo.paused)
1054  resume_record();
1055 
1056  update_status();
1057 
1058  cl.frameflags = 0;
1059 
1060 done:
1061  cls.demo.seeking = qfalse;
1062 }

◆ CL_Stop_f()

void CL_Stop_f ( void  )

Definition at line 268 of file demo.c.

269 {
270  uint32_t msglen;
271  char buffer[MAX_QPATH];
272 
273  if (!cls.demo.recording) {
274  Com_Printf("Not recording a demo.\n");
275  return;
276  }
277 
278 // finish up
279  msglen = (uint32_t)-1;
280  FS_Write(&msglen, 4, cls.demo.recording);
281 
282  format_demo_size(buffer, sizeof(buffer));
283 
284 // close demofile
286  cls.demo.recording = 0;
287  cls.demo.paused = qfalse;
288  cls.demo.frames_written = 0;
289  cls.demo.frames_dropped = 0;
290  cls.demo.others_dropped = 0;
291 
292 // print some statistics
293  Com_Printf("Stopped demo (%s).\n", buffer);
294 
295 // tell the server we finished recording
297 }

Referenced by CL_Changing_f(), CL_CleanupDemos(), and CL_WriteDemoMessage().

◆ CL_Suspend_f()

static void CL_Suspend_f ( void  )
static

Definition at line 499 of file demo.c.

500 {
501  if (!cls.demo.recording) {
502  Com_Printf("Not recording a demo.\n");
503  return;
504  }
505 
506  if (!cls.demo.paused) {
507  Com_Printf("Suspended demo recording.\n");
508  cls.demo.paused = qtrue;
509  return;
510  }
511 
512  resume_record();
513 
514  if (!cls.demo.recording)
515  // write failed
516  return;
517 
518  Com_Printf("Resumed demo recording.\n");
519 
520  cls.demo.paused = qfalse;
521 
522  // clear dirty configstrings
523  memset(cl.dcs, 0, sizeof(cl.dcs));
524 }

◆ CL_WriteDemoMessage()

qboolean CL_WriteDemoMessage ( sizebuf_t *  buf)

Definition at line 41 of file demo.c.

42 {
43  uint32_t msglen;
44  ssize_t ret;
45 
46  if (buf->overflowed) {
47  SZ_Clear(buf);
48  Com_WPrintf("Demo message overflowed (should never happen).\n");
49  return qtrue;
50  }
51 
52  if (!buf->cursize)
53  return qtrue;
54 
55  msglen = LittleLong(buf->cursize);
56  ret = FS_Write(&msglen, 4, cls.demo.recording);
57  if (ret != 4)
58  goto fail;
59  ret = FS_Write(buf->data, buf->cursize, cls.demo.recording);
60  if (ret != buf->cursize)
61  goto fail;
62 
63  Com_DDPrintf("%s: wrote %"PRIz" bytes\n", __func__, buf->cursize);
64 
65  SZ_Clear(buf);
66  return qtrue;
67 
68 fail:
69  SZ_Clear(buf);
70  Com_EPrintf("Couldn't write demo: %s\n", Q_ErrorString(ret));
71  CL_Stop_f();
72  return qfalse;
73 }

Referenced by CL_PacketEvent(), CL_Record_f(), parse_next_message(), and resume_record().

◆ emit_delta_frame()

static void emit_delta_frame ( server_frame_t from,
server_frame_t to,
int  fromnum,
int  tonum 
)
static

Definition at line 145 of file demo.c.

147 {
148  player_packed_t oldpack, newpack;
149 
150  MSG_WriteByte(svc_frame);
151  MSG_WriteLong(tonum);
152  MSG_WriteLong(fromnum); // what we are delta'ing from
153  MSG_WriteByte(0); // rate dropped packets
154 
155  // send over the areabits
157  MSG_WriteData(to->areabits, to->areabytes);
158 
159  // delta encode the playerstate
160  MSG_WriteByte(svc_playerinfo);
161  MSG_PackPlayer(&newpack, &to->ps);
162  if (from) {
163  MSG_PackPlayer(&oldpack, &from->ps);
164  MSG_WriteDeltaPlayerstate_Default(&oldpack, &newpack);
165  } else {
166  MSG_WriteDeltaPlayerstate_Default(NULL, &newpack);
167  }
168 
169  // delta encode the entities
170  MSG_WriteByte(svc_packetentities);
171  emit_packet_entities(from, to);
172 }

Referenced by CL_EmitDemoFrame(), and CL_EmitDemoSnapshot().

◆ emit_packet_entities()

static void emit_packet_entities ( server_frame_t from,
server_frame_t to 
)
static

Definition at line 76 of file demo.c.

77 {
78  entity_packed_t oldpack, newpack;
79  entity_state_t *oldent, *newent;
80  int oldindex, newindex;
81  int oldnum, newnum;
82  int i, from_num_entities;
83 
84  if (!from)
85  from_num_entities = 0;
86  else
87  from_num_entities = from->numEntities;
88 
89  newindex = 0;
90  oldindex = 0;
91  oldent = newent = 0;
92  while (newindex < to->numEntities || oldindex < from_num_entities) {
93  if (newindex >= to->numEntities) {
94  newnum = 9999;
95  } else {
96  i = (to->firstEntity + newindex) & PARSE_ENTITIES_MASK;
97  newent = &cl.entityStates[i];
98  newnum = newent->number;
99  }
100 
101  if (oldindex >= from_num_entities) {
102  oldnum = 9999;
103  } else {
104  i = (from->firstEntity + oldindex) & PARSE_ENTITIES_MASK;
105  oldent = &cl.entityStates[i];
106  oldnum = oldent->number;
107  }
108 
109  if (newnum == oldnum) {
110  // Delta update from old position. Because the force parm is false,
111  // this will not result in any bytes being emitted if the entity has
112  // not changed at all. Note that players are always 'newentities',
113  // this updates their old_origin always and prevents warping in case
114  // of packet loss.
115  MSG_PackEntity(&oldpack, oldent, qfalse);
116  MSG_PackEntity(&newpack, newent, qfalse);
117  MSG_WriteDeltaEntity(&oldpack, &newpack,
118  newent->number <= cl.maxclients ? MSG_ES_NEWENTITY : 0);
119  oldindex++;
120  newindex++;
121  continue;
122  }
123 
124  if (newnum < oldnum) {
125  // this is a new entity, send it from the baseline
126  MSG_PackEntity(&oldpack, &cl.baselines[newnum], qfalse);
127  MSG_PackEntity(&newpack, newent, qfalse);
128  MSG_WriteDeltaEntity(&oldpack, &newpack, MSG_ES_FORCE | MSG_ES_NEWENTITY);
129  newindex++;
130  continue;
131  }
132 
133  if (newnum > oldnum) {
134  // the old entity isn't present in the new message
135  MSG_PackEntity(&oldpack, oldent, qfalse);
136  MSG_WriteDeltaEntity(&oldpack, NULL, MSG_ES_FORCE);
137  oldindex++;
138  continue;
139  }
140  }
141 
142  MSG_WriteShort(0); // end of packetentities
143 }

Referenced by emit_delta_frame().

◆ find_snapshot()

static demosnap_t* find_snapshot ( int  framenum)
static

Definition at line 851 of file demo.c.

852 {
853  demosnap_t *snap, *prev;
854 
855  if (LIST_EMPTY(&cls.demo.snapshots))
856  return NULL;
857 
858  prev = LIST_FIRST(demosnap_t, &cls.demo.snapshots, entry);
859 
860  LIST_FOR_EACH(demosnap_t, snap, &cls.demo.snapshots, entry) {
861  if (snap->framenum > framenum)
862  break;
863  prev = snap;
864  }
865 
866  return prev;
867 }

Referenced by CL_Seek_f().

◆ finish_demo()

static void finish_demo ( int  ret)
static

Definition at line 622 of file demo.c.

623 {
624  char *s = Cvar_VariableString("nextserver");
625 
626  if (!s[0]) {
627  if (ret == 0) {
628  Com_Error(ERR_DISCONNECT, "Demo finished");
629  } else {
630  Com_Error(ERR_DROP, "Couldn't read demo: %s", Q_ErrorString(ret));
631  }
632  }
633 
634  CL_Disconnect(ERR_RECONNECT);
635 
636  Cvar_Set("nextserver", "");
637 
639  Cbuf_AddText(&cmd_buffer, "\n");
641 }

Referenced by CL_DemoFrame(), CL_Seek_f(), and parse_next_message().

◆ format_demo_size()

static size_t format_demo_size ( char *  buffer,
size_t  size 
)
static

Definition at line 230 of file demo.c.

231 {
232  return Com_FormatSizeLong(buffer, size, FS_Tell(cls.demo.recording));
233 }

Referenced by CL_Stop_f(), and format_demo_status().

◆ format_demo_status()

static size_t format_demo_status ( char *  buffer,
size_t  size 
)
static

Definition at line 235 of file demo.c.

236 {
237  size_t len = format_demo_size(buffer, size);
238  int min, sec, frames = cls.demo.frames_written;
239 
240  sec = frames / 10; frames %= 10;
241  min = sec / 60; sec %= 60;
242 
243  len += Q_scnprintf(buffer + len, size - len, ", %d:%02d.%d",
244  min, sec, frames);
245 
246  if (cls.demo.frames_dropped) {
247  len += Q_scnprintf(buffer + len, size - len, ", %d frame%s dropped",
249  cls.demo.frames_dropped == 1 ? "" : "s");
250  }
251 
252  if (cls.demo.others_dropped) {
253  len += Q_scnprintf(buffer + len, size - len, ", %d message%s dropped",
255  cls.demo.others_dropped == 1 ? "" : "s");
256  }
257 
258  return len;
259 }

Referenced by CL_Record_f().

◆ parse_info_string()

static void parse_info_string ( demoInfo_t *  info,
int  clientNum,
int  index,
const char *  string 
)
static

Definition at line 1064 of file demo.c.

1065 {
1066  size_t len;
1067  char *p;
1068 
1069  if (index >= CS_PLAYERSKINS && index < CS_PLAYERSKINS + MAX_CLIENTS) {
1070  if (index - CS_PLAYERSKINS == clientNum) {
1071  Q_strlcpy(info->pov, string, sizeof(info->pov));
1072  p = strchr(info->pov, '\\');
1073  if (p) {
1074  *p = 0;
1075  }
1076  }
1077  } else if (index == CS_MODELS + 1) {
1078  len = strlen(string);
1079  if (len > 9) {
1080  memcpy(info->map, string + 5, len - 9); // skip "maps/"
1081  info->map[len - 9] = 0; // cut off ".bsp"
1082  }
1083  }
1084 }

Referenced by CL_GetDemoInfo().

◆ parse_next_message()

static int parse_next_message ( int  wait)
static

Definition at line 655 of file demo.c.

656 {
657  int ret;
658 
660  if (ret < 0 || (ret == 0 && wait == 0)) {
661  finish_demo(ret);
662  return -1;
663  }
664 
665  update_status();
666 
667  if (ret == 0) {
668  cls.demo.eof = qtrue;
669  return -1;
670  }
671 
673 
674  // if recording demo, write the message out
677  }
678 
679  // if running GTV server, transmit to client
680  CL_GTV_Transmit();
681 
682  // save a snapshot once the full packet is parsed
684 
685  return 0;
686 }

Referenced by CL_DemoFrame(), and CL_PlayDemo_f().

◆ read_first_message()

static int read_first_message ( qhandle_t  f)
static

Definition at line 526 of file demo.c.

527 {
528  uint32_t ul;
529  uint16_t us;
530  size_t msglen;
531  ssize_t read;
532  qerror_t ret;
533  int type;
534 
535  // read magic/msglen
536  read = FS_Read(&ul, 4, f);
537  if (read != 4) {
538  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
539  }
540 
541  // check for gzip header
542  if (CHECK_GZIP_HEADER(ul)) {
543  ret = FS_FilterFile(f);
544  if (ret) {
545  return ret;
546  }
547  read = FS_Read(&ul, 4, f);
548  if (read != 4) {
549  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
550  }
551  }
552 
553  // determine demo type
554  if (ul == MVD_MAGIC) {
555  read = FS_Read(&us, 2, f);
556  if (read != 2) {
557  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
558  }
559  if (!us) {
560  return Q_ERR_UNEXPECTED_EOF;
561  }
562  msglen = LittleShort(us);
563  type = 1;
564  } else {
565  if (ul == (uint32_t)-1) {
566  return Q_ERR_UNEXPECTED_EOF;
567  }
568  msglen = LittleLong(ul);
569  type = 0;
570  }
571 
572  // if (msglen < 64 || msglen > sizeof(msg_read_buffer)) {
573  if (msglen > sizeof(msg_read_buffer)) {
574  return Q_ERR_INVALID_FORMAT;
575  }
576 
578  msg_read.cursize = msglen;
579 
580  // read packet data
581  read = FS_Read(msg_read.data, msglen, f);
582  if (read != msglen) {
583  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
584  }
585 
586  return type;
587 }

Referenced by CL_GetDemoInfo(), and CL_PlayDemo_f().

◆ read_next_message()

static int read_next_message ( qhandle_t  f)
static

Definition at line 589 of file demo.c.

590 {
591  uint32_t msglen;
592  ssize_t read;
593 
594  // read msglen
595  read = FS_Read(&msglen, 4, f);
596  if (read != 4) {
597  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
598  }
599 
600  // check for EOF packet
601  if (msglen == (uint32_t)-1) {
602  return 0;
603  }
604 
605  msglen = LittleLong(msglen);
606  if (msglen > sizeof(msg_read_buffer)) {
607  return Q_ERR_INVALID_FORMAT;
608  }
609 
611  msg_read.cursize = msglen;
612 
613  // read packet data
614  read = FS_Read(msg_read.data, msglen, f);
615  if (read != msglen) {
616  return read < 0 ? read : Q_ERR_UNEXPECTED_EOF;
617  }
618 
619  return 1;
620 }

Referenced by CL_GetDemoInfo(), CL_Seek_f(), and parse_next_message().

◆ resume_record()

static void resume_record ( void  )
static

Definition at line 454 of file demo.c.

455 {
456  int i, j, index;
457  size_t len;
458  char *s;
459 
460  // write dirty configstrings
461  for (i = 0; i < CS_BITMAP_LONGS; i++) {
462  if (((uint32_t *)cl.dcs)[i] == 0)
463  continue;
464 
465  index = i << 5;
466  for (j = 0; j < 32; j++, index++) {
467  if (!Q_IsBitSet(cl.dcs, index))
468  continue;
469 
470  s = cl.configstrings[index];
471 
472  len = strlen(s);
473  if (len > MAX_QPATH)
474  len = MAX_QPATH;
475 
476  if (cls.demo.buffer.cursize + len + 4 > cls.demo.buffer.maxsize) {
478  return;
479  // multiple packets = not seamless
480  }
481 
482  SZ_WriteByte(&cls.demo.buffer, svc_configstring);
483  SZ_WriteShort(&cls.demo.buffer, index);
484  SZ_Write(&cls.demo.buffer, s, len);
486  }
487  }
488 
489  // write delta uncompressed frame
490  //cls.demo.last_server_frame = -1;
492 
493  // FIXME: write layout if it fits? most likely it won't
494 
495  // write it to the demo file
497 }

Referenced by CL_Seek_f(), and CL_Suspend_f().

◆ update_status()

static void update_status ( void  )
static

Definition at line 643 of file demo.c.

644 {
645  if (cls.demo.file_size) {
646  off_t pos = FS_Tell(cls.demo.playback);
647 
648  if (pos > cls.demo.file_offset)
650  else
651  cls.demo.file_percent = 0;
652  }
653 }

Referenced by CL_Seek_f(), and parse_next_message().

Variable Documentation

◆ c_demo

const cmdreg_t c_demo[]
static
Initial value:
= {
{ "demo", CL_PlayDemo_f, CL_Demo_c },
{ "record", CL_Record_f, CL_Demo_c },
{ "stop", CL_Stop_f },
{ "suspend", CL_Suspend_f },
{ "seek", CL_Seek_f },
{ NULL }
}

Definition at line 1258 of file demo.c.

Referenced by CL_InitDemos().

◆ cl_demomsglen

cvar_t* cl_demomsglen
static

Definition at line 28 of file demo.c.

Referenced by CL_InitDemos(), and CL_Record_f().

◆ cl_demosnaps

cvar_t* cl_demosnaps
static

Definition at line 27 of file demo.c.

Referenced by CL_EmitDemoSnapshot(), and CL_InitDemos().

◆ cl_demowait

cvar_t* cl_demowait
static

Definition at line 29 of file demo.c.

Referenced by CL_DemoFrame(), CL_InitDemos(), and CL_Seek_f().

◆ demo_buffer

byte demo_buffer[MAX_PACKETLEN]
static

Definition at line 25 of file demo.c.

Referenced by CL_Record_f().

◆ o_record

const cmd_option_t o_record[]
static
Initial value:
= {
{ "h", "help", "display this message" },
{ "z", "compress", "compress demo with gzip" },
{ "e", "extended", "use extended packet size" },
{ "s", "standard", "use standard packet size" },
{ NULL }
}

Definition at line 299 of file demo.c.

Referenced by CL_Record_f(), MVD_StreamedRecord_f(), and SV_MvdRecord_f().

client_state_s::frame
server_frame_t frame
Definition: client.h:212
server_frame_t::valid
qboolean valid
Definition: client.h:129
SV_Shutdown
void SV_Shutdown(const char *finalmsg, error_type_t type)
Definition: main.c:2252
FRAME_CUR
#define FRAME_CUR
Definition: demo.c:177
client_state_s::configstrings
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: client.h:289
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
FS_EasyOpenFile
qhandle_t FS_EasyOpenFile(char *buf, size_t size, unsigned mode, const char *dir, const char *name, const char *ext)
Definition: files.c:1846
find_snapshot
static demosnap_t * find_snapshot(int framenum)
Definition: demo.c:851
CL_UpdateRecordingSetting
void CL_UpdateRecordingSetting(void)
Definition: main.c:265
msg_read
sizebuf_t msg_read
Definition: msg.c:37
client_state_s::entityStates
entity_state_t entityStates[MAX_PARSE_ENTITIES]
Definition: client.h:204
parse_next_message
static int parse_next_message(int wait)
Definition: demo.c:655
client_state_s::servertime
int servertime
Definition: client.h:214
msg_read_buffer
byte msg_read_buffer[MAX_MSGLEN]
Definition: msg.c:38
client_static_s::playback
qhandle_t playback
Definition: client.h:453
cmd_optarg
char * cmd_optarg
Definition: cmd.c:848
client_static_s::last_server_frame
int last_server_frame
Definition: client.h:457
Com_FormatSizeLong
size_t Com_FormatSizeLong(char *dest, size_t destsize, off_t bytes)
Definition: utils.c:482
client_static_s::demo
struct client_static_s::@3 demo
FS_Read
ssize_t FS_Read(void *buf, size_t len, qhandle_t f)
Definition: files.c:1547
client_static_s::buffer
sizebuf_t buffer
Definition: client.h:466
parse_info_string
static void parse_info_string(demoInfo_t *info, int clientNum, int index, const char *string)
Definition: demo.c:1064
FS_FilterFile
qerror_t FS_FilterFile(qhandle_t f)
Definition: files.c:661
S_StopAllSounds
void S_StopAllSounds(void)
Definition: main.c:932
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
cl_cmdbuf
cmdbuf_t cl_cmdbuf
Definition: main.c:104
client_static_s::last_snapshot
int last_snapshot
Definition: client.h:462
CL_ClearTEnts
void CL_ClearTEnts(void)
Definition: tent.c:1459
client_static_s::file_percent
int file_percent
Definition: client.h:465
SCR_UpdateScreen
void SCR_UpdateScreen(void)
Definition: screen.c:2142
demo_buffer
static byte demo_buffer[MAX_PACKETLEN]
Definition: demo.c:25
emit_packet_entities
static void emit_packet_entities(server_frame_t *from, server_frame_t *to)
Definition: demo.c:76
ca_active
@ ca_active
Definition: client.h:340
CL_Seek_f
static void CL_Seek_f(void)
Definition: demo.c:903
client_static_s::time_start
unsigned time_start
Definition: client.h:455
demosnap_t::filepos
off_t filepos
Definition: demo.c:760
CL_Demo_c
static void CL_Demo_c(genctx_t *ctx, int argnum)
Definition: demo.c:750
client_static_s::state
connstate_t state
Definition: client.h:375
client_state_s::gamedir
char gamedir[MAX_QPATH]
Definition: client.h:277
ca_connected
@ ca_connected
Definition: client.h:337
SZ_WriteByte
void SZ_WriteByte(sizebuf_t *sb, int c)
Definition: sizebuf.c:82
client_state_s::dcs
byte dcs[CS_BITMAP_BYTES]
Definition: client.h:223
SZ_WriteShort
void SZ_WriteShort(sizebuf_t *sb, int c)
Definition: sizebuf.c:90
FS_Tell
ssize_t FS_Tell(qhandle_t f)
Definition: files.c:505
Cmd_PrintUsage
void Cmd_PrintUsage(const cmd_option_t *opt, const char *suffix)
Definition: cmd.c:1143
client_state_s::oldframe
server_frame_t oldframe
Definition: client.h:213
CL_WriteDemoMessage
qboolean CL_WriteDemoMessage(sizebuf_t *buf)
Definition: demo.c:41
client_state_s::serverdelta
int serverdelta
Definition: client.h:215
CL_SeekDemoMessage
void CL_SeekDemoMessage(void)
Definition: parse.c:1343
Cbuf_InsertText
void Cbuf_InsertText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:128
client_static_s::frames_written
int frames_written
Definition: client.h:458
format_demo_size
static size_t format_demo_size(char *buffer, size_t size)
Definition: demo.c:230
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
read_first_message
static int read_first_message(qhandle_t f)
Definition: demo.c:526
com_timedemo
cvar_t * com_timedemo
Definition: common.c:97
client_state_s::baseconfigstrings
char baseconfigstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: client.h:288
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
svc_stufftext
#define svc_stufftext
Definition: g_local.h:41
Sys_Milliseconds
unsigned Sys_Milliseconds(void)
Definition: system.c:644
SZ_Init
void SZ_Init(sizebuf_t *buf, void *data, size_t size)
Definition: sizebuf.c:31
update_status
static void update_status(void)
Definition: demo.c:643
CL_Disconnect
void CL_Disconnect(error_type_t type)
Definition: main.c:740
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
CL_Stop_f
void CL_Stop_f(void)
Definition: demo.c:268
read_next_message
static int read_next_message(qhandle_t f)
Definition: demo.c:589
server_frame_t::areabytes
int areabytes
Definition: client.h:135
client_static_s::recording
qhandle_t recording
Definition: client.h:454
client_state_s::servercount
int servercount
Definition: client.h:276
FS_FOpenFile
ssize_t FS_FOpenFile(const char *name, qhandle_t *f, unsigned mode)
Definition: files.c:1692
cmd_buffer
cmdbuf_t cmd_buffer
Definition: cmd.c:49
client_static_s::seeking
qboolean seeking
Definition: client.h:469
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
demosnap_t
Definition: demo.c:757
client_state_s::frameflags
unsigned frameflags
Definition: client.h:210
MSG_PackEntity
void MSG_PackEntity(entity_packed_t *out, const entity_state_t *in, qboolean short_angles)
Definition: msg.c:468
client_state_s::clientNum
int clientNum
Definition: client.h:278
MSG_PackPlayer
void MSG_PackPlayer(player_packed_t *out, const player_state_t *in)
Definition: msg.c:763
client_static_s::others_dropped
int others_dropped
Definition: client.h:460
emit_delta_frame
static void emit_delta_frame(server_frame_t *from, server_frame_t *to, int fromnum, int tonum)
Definition: demo.c:145
Cmd_ParseOptions
int Cmd_ParseOptions(const cmd_option_t *opt)
Definition: cmd.c:1057
msg_write
sizebuf_t msg_write
Definition: msg.c:34
client_state_s::baselines
entity_state_t baselines[MAX_EDICTS]
Definition: client.h:202
client_static_s::frames_read
int frames_read
Definition: client.h:461
c_demo
static const cmdreg_t c_demo[]
Definition: demo.c:1258
Cbuf_AddText
void Cbuf_AddText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:95
va
char * va(const char *format,...)
Definition: shared.c:429
FS_File_g
void FS_File_g(const char *path, const char *ext, unsigned flags, genctx_t *ctx)
Definition: files.c:2954
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
CL_EmitDemoFrame
void CL_EmitDemoFrame(void)
Definition: demo.c:186
CL_ClearEffects
void CL_ClearEffects(void)
Definition: effects.c:2067
client_state_s::layout
char layout[MAX_NET_STRING]
Definition: client.h:269
CL_Record_f
static void CL_Record_f(void)
Definition: demo.c:316
server_frame_t::areabits
byte areabits[MAX_MAP_AREA_BYTES]
Definition: client.h:134
cl_demowait
static cvar_t * cl_demowait
Definition: demo.c:29
Cmd_Register
void Cmd_Register(const cmdreg_t *reg)
Definition: cmd.c:1572
MSG_ReadLong
int MSG_ReadLong(void)
Definition: msg.c:1517
MSG_WriteDeltaEntity
void MSG_WriteDeltaEntity(const entity_packed_t *from, const entity_packed_t *to, msgEsFlags_t flags)
Definition: msg.c:505
client_state_s::time
int time
Definition: client.h:244
format_demo_status
static size_t format_demo_status(char *buffer, size_t size)
Definition: demo.c:235
cl_demosnaps
static cvar_t * cl_demosnaps
Definition: demo.c:27
client_static_s::servername
char servername[MAX_OSPATH]
Definition: client.h:410
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
MSG_WriteShort
void MSG_WriteShort(int c)
Definition: msg.c:125
cl_demomsglen
static cvar_t * cl_demomsglen
Definition: demo.c:28
server_frame_t
Definition: client.h:128
o_record
static const cmd_option_t o_record[]
Definition: demo.c:299
CL_PlayDemo_f
static void CL_PlayDemo_f(void)
Definition: demo.c:693
CL_Suspend_f
static void CL_Suspend_f(void)
Definition: demo.c:499
FS_Length
ssize_t FS_Length(qhandle_t f)
Definition: files.c:487
CL_UpdateConfigstring
void CL_UpdateConfigstring(int index)
Definition: precache.c:417
cl
client_state_t cl
Definition: main.c:99
FS_Write
ssize_t FS_Write(const void *buf, size_t len, qhandle_t f)
Definition: files.c:1643
demosnap_t::entry
list_t entry
Definition: demo.c:758
cls
client_static_t cls
Definition: main.c:98
client_state_s::frames
server_frame_t frames[UPDATE_BACKUP]
Definition: client.h:209
MSG_WriteString
void MSG_WriteString(const char *string)
Definition: msg.c:160
c
statCounters_t c
Definition: main.c:30
demosnap_t::framenum
int framenum
Definition: demo.c:759
client_state_s::numEntityStates
int numEntityStates
Definition: client.h:205
MSG_WriteLong
void MSG_WriteLong(int c)
Definition: msg.c:144
client_static_s::eof
qboolean eof
Definition: client.h:470
server_frame_t::numEntities
int numEntities
Definition: client.h:140
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
MSG_ReadString
size_t MSG_ReadString(char *dest, size_t size)
Definition: msg.c:1531
server_frame_t::ps
player_state_t ps
Definition: client.h:137
demosnap_t::msglen
size_t msglen
Definition: demo.c:761
COM_SkipPath
char * COM_SkipPath(const char *pathname)
Definition: shared.c:152
client_static_s::frames_dropped
int frames_dropped
Definition: client.h:459
Cbuf_Execute
void Cbuf_Execute(cmdbuf_t *buf)
Definition: cmd.c:152
Cmd_PrintHelp
void Cmd_PrintHelp(const cmd_option_t *opt)
Definition: cmd.c:1160
CL_DeltaFrame
void CL_DeltaFrame(void)
Definition: entities.c:358
finish_demo
static void finish_demo(int ret)
Definition: demo.c:622
Cmd_PrintHint
void Cmd_PrintHint(void)
Definition: cmd.c:1178
Con_Popup
void Con_Popup(qboolean force)
Definition: console.c:152
server_frame_t::number
int number
Definition: client.h:131
pack
static uint32_t pack(uint64_t n)
Definition: hq2x.c:99
client_static_s::time_frames
unsigned time_frames
Definition: client.h:456
svc_layout
#define svc_layout
Definition: g_local.h:39
sv_running
cvar_t * sv_running
Definition: common.c:95
Cvar_VariableString
char * Cvar_VariableString(const char *var_name)
Definition: cvar.c:122
FRAME_PRE
#define FRAME_PRE
Definition: demo.c:176
FS_FCloseFile
void FS_FCloseFile(qhandle_t f)
Definition: files.c:759
client_static_s::snapshots
list_t snapshots
Definition: client.h:467
MSG_ReadByte
int MSG_ReadByte(void)
Definition: msg.c:1475
client_static_s::serverAddress
netadr_t serverAddress
Definition: client.h:409
FS_Seek
qerror_t FS_Seek(qhandle_t f, off_t offset)
Definition: files.c:564
client_state_s::maxclients
int maxclients
Definition: client.h:279
client_static_s::file_size
int file_size
Definition: client.h:463
client_static_s::file_offset
int file_offset
Definition: client.h:464
CL_GTV_Transmit
void CL_GTV_Transmit(void)
Definition: gtv.c:278
CL_EmitDemoSnapshot
void CL_EmitDemoSnapshot(void)
Definition: demo.c:773
Q_scnprintf
size_t Q_scnprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:867
CL_ParseServerMessage
void CL_ParseServerMessage(void)
Definition: parse.c:1168
server_frame_t::firstEntity
int firstEntity
Definition: client.h:141
demosnap_t::data
byte data[1]
Definition: demo.c:762
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
CL_FRAMESYNC
#define CL_FRAMESYNC
Definition: client.h:164
MSG_WriteDeltaPlayerstate_Default
void MSG_WriteDeltaPlayerstate_Default(const player_packed_t *from, const player_packed_t *to)
Definition: msg.c:795
MSG_ReadShort
int MSG_ReadShort(void)
Definition: msg.c:1489
client_static_s::paused
qboolean paused
Definition: client.h:468
resume_record
static void resume_record(void)
Definition: demo.c:454