Quake II RTX doxygen  1.0 dev
mvd.c File Reference
#include "server.h"
#include "server/mvd/protocol.h"

Go to the source code of this file.

Classes

struct  gtv_client_t
 
struct  mvd_server_t
 

Macros

#define FOR_EACH_GTV(client)   LIST_FOR_EACH(gtv_client_t, client, &gtv_client_list, entry)
 
#define FOR_EACH_ACTIVE_GTV(client)   LIST_FOR_EACH(gtv_client_t, client, &gtv_active_list, active)
 
#define MVD_USERINFO1   "\\name\\[MVDSPEC]\\skin\\male/grunt"
 
#define MVD_USERINFO2   "\\mvdspec\\" STRINGIFY(PROTOCOL_VERSION_MVD_CURRENT) "\\ip\\loopback"
 

Functions

static LIST_DECL (gtv_client_list)
 
static LIST_DECL (gtv_active_list)
 
static LIST_DECL (gtv_white_list)
 
static LIST_DECL (gtv_black_list)
 
static qboolean mvd_enable (void)
 
static void mvd_disable (void)
 
static void mvd_error (const char *reason)
 
static void write_stream (gtv_client_t *client, void *data, size_t len)
 
static void write_message (gtv_client_t *client, gtv_serverop_t op)
 
static void rec_stop (void)
 
static qboolean rec_allowed (void)
 
static void rec_start (qhandle_t demofile)
 
static void rec_write (void)
 
static void dummy_wait_f (void)
 
static void dummy_command (void)
 
static void dummy_forward_f (void)
 
static void dummy_record_f (void)
 
static void dummy_stop_f (void)
 
static void dummy_exec_string (cmdbuf_t *buf, const char *line)
 
static void dummy_add_message (client_t *client, byte *data, size_t length, qboolean reliable)
 
static void dummy_spawn (void)
 
static client_tdummy_find_slot (void)
 
static int dummy_create (void)
 
static void dummy_run (void)
 
static qboolean player_is_active (const edict_t *ent)
 
static qboolean entity_is_active (const edict_t *ent)
 
static void build_gamestate (void)
 
static void emit_gamestate (void)
 
static void copy_entity_state (entity_packed_t *dst, const entity_packed_t *src, int flags)
 
static void emit_frame (void)
 
static void suspend_streams (void)
 
static void resume_streams (void)
 
static qboolean players_active (void)
 
static void check_clients_activity (void)
 
static void check_players_activity (void)
 
static void rec_frame (size_t total)
 
void SV_MvdBeginFrame (void)
 
void SV_MvdEndFrame (void)
 
void SV_MvdMulticast (int leafnum, multicast_t to)
 
static qboolean filter_unicast_data (edict_t *ent)
 
void SV_MvdUnicast (edict_t *ent, int clientNum, qboolean reliable)
 
void SV_MvdConfigstring (int index, const char *string, size_t len)
 
void SV_MvdBroadcastPrint (int level, const char *string)
 
void SV_MvdStartSound (int entnum, int channel, int flags, int soundindex, int volume, int attenuation, int timeofs)
 
static void remove_client (gtv_client_t *client)
 
static void drop_client (gtv_client_t *client, const char *error)
 
static qboolean auth_client (gtv_client_t *client, const char *password)
 
static void parse_hello (gtv_client_t *client)
 
static void parse_ping (gtv_client_t *client)
 
static void parse_stream_start (gtv_client_t *client)
 
static void parse_stream_stop (gtv_client_t *client)
 
static void parse_stringcmd (gtv_client_t *client)
 
static qboolean parse_message (gtv_client_t *client)
 
static gtv_client_tfind_slot (void)
 
static void accept_client (netstream_t *stream)
 
void SV_MvdRunClients (void)
 
static void dump_clients (void)
 
static void dump_versions (void)
 
void SV_MvdStatus_f (void)
 
static void mvd_drop (gtv_serverop_t op)
 
void SV_MvdMapChanged (void)
 
void SV_MvdClientDropped (client_t *client)
 
void SV_MvdInit (void)
 
void SV_MvdShutdown (error_type_t type)
 
void SV_MvdRecord_f (void)
 
void SV_MvdStop_f (void)
 
static void SV_MvdStuff_f (void)
 
static void SV_AddGtvHost_f (void)
 
static void SV_DelGtvHost_f (void)
 
static void SV_ListGtvHosts_f (void)
 
static void SV_AddGtvBan_f (void)
 
static void SV_DelGtvBan_f (void)
 
static void SV_ListGtvBans_f (void)
 
void SV_MvdRegister (void)
 

Variables

static mvd_server_t mvd
 
static cvar_t * sv_mvd_enable
 
static cvar_t * sv_mvd_maxclients
 
static cvar_t * sv_mvd_bufsize
 
static cvar_t * sv_mvd_password
 
static cvar_t * sv_mvd_noblend
 
static cvar_t * sv_mvd_nogun
 
static cvar_t * sv_mvd_nomsgs
 
static cvar_t * sv_mvd_maxsize
 
static cvar_t * sv_mvd_maxtime
 
static cvar_t * sv_mvd_maxmaps
 
static cvar_t * sv_mvd_begincmd
 
static cvar_t * sv_mvd_scorecmd
 
static cvar_t * sv_mvd_autorecord
 
static cvar_t * sv_mvd_capture_flags
 
static cvar_t * sv_mvd_disconnect_time
 
static cvar_t * sv_mvd_suspend_time
 
static cvar_t * sv_mvd_allow_stufftext
 
static cvar_t * sv_mvd_spawn_dummy
 
static cmdbuf_t dummy_buffer
 
static char dummy_buffer_text [MAX_STRING_CHARS]
 
static const ucmd_t dummy_cmds []
 
static const cmdreg_t c_svmvd []
 

Macro Definition Documentation

◆ FOR_EACH_ACTIVE_GTV

#define FOR_EACH_ACTIVE_GTV (   client)    LIST_FOR_EACH(gtv_client_t, client, &gtv_active_list, active)

Definition at line 29 of file mvd.c.

◆ FOR_EACH_GTV

#define FOR_EACH_GTV (   client)    LIST_FOR_EACH(gtv_client_t, client, &gtv_client_list, entry)

Definition at line 26 of file mvd.c.

◆ MVD_USERINFO1

#define MVD_USERINFO1   "\\name\\[MVDSPEC]\\skin\\male/grunt"

Definition at line 336 of file mvd.c.

◆ MVD_USERINFO2

#define MVD_USERINFO2   "\\mvdspec\\" STRINGIFY(PROTOCOL_VERSION_MVD_CURRENT) "\\ip\\loopback"

Definition at line 339 of file mvd.c.

Function Documentation

◆ accept_client()

static void accept_client ( netstream_t *  stream)
static

Definition at line 1728 of file mvd.c.

1729 {
1730  gtv_client_t *client;
1731  netstream_t *s;
1732 
1733  // limit number of connections from single IPv4 address or /48 IPv6 network
1734  if (sv_iplimit->integer > 0) {
1735  int count = 0;
1736 
1737  FOR_EACH_GTV(client) {
1738  if (stream->address.type != client->stream.address.type)
1739  continue;
1740  if (stream->address.type == NA_IP && stream->address.ip.u32[0] != client->stream.address.ip.u32[0])
1741  continue;
1742  if (stream->address.type == NA_IP6 && memcmp(stream->address.ip.u8, client->stream.address.ip.u8, 48 / CHAR_BIT))
1743  continue;
1744  count++;
1745  }
1746  if (count >= sv_iplimit->integer) {
1747  Com_Printf("TCP client [%s] rejected: too many connections\n",
1748  NET_AdrToString(&stream->address));
1749  NET_CloseStream(stream);
1750  return;
1751  }
1752  }
1753 
1754  // find a free client slot
1755  client = find_slot();
1756  if (!client) {
1757  Com_Printf("TCP client [%s] rejected: no free slots\n",
1758  NET_AdrToString(&stream->address));
1759  NET_CloseStream(stream);
1760  return;
1761  }
1762 
1763  memset(client, 0, sizeof(*client));
1764 
1765  s = &client->stream;
1766  s->recv.data = client->buffer;
1767  s->recv.size = MAX_GTC_MSGLEN;
1768  s->send.data = client->buffer + MAX_GTC_MSGLEN;
1769  s->send.size = 4; // need no more than that initially
1770  s->socket = stream->socket;
1771  s->address = stream->address;
1772  s->state = stream->state;
1773 
1774  client->lastmessage = svs.realtime;
1775  client->state = cs_assigned;
1776  List_SeqAdd(&gtv_client_list, &client->entry);
1777  List_Init(&client->active);
1778 
1779  Com_DPrintf("TCP client [%s] accepted\n",
1780  NET_AdrToString(&stream->address));
1781 }

Referenced by SV_MvdRunClients().

◆ auth_client()

static qboolean auth_client ( gtv_client_t client,
const char *  password 
)
static

Definition at line 1440 of file mvd.c.

1441 {
1442  if (SV_MatchAddress(&gtv_white_list, &client->stream.address))
1443  return qtrue; // ALLOW whitelisted hosts without password
1444 
1445  if (SV_MatchAddress(&gtv_black_list, &client->stream.address))
1446  return qfalse; // DENY blacklisted hosts
1447 
1448  if (*sv_mvd_password->string == 0)
1449  return qtrue; // ALLOW neutral hosts if password IS NOT set
1450 
1451  // ALLOW neutral hosts if password matches, DENY otherwise
1452  return !strcmp(sv_mvd_password->string, password);
1453 }

Referenced by parse_hello().

◆ build_gamestate()

static void build_gamestate ( void  )
static

Definition at line 560 of file mvd.c.

561 {
562  edict_t *ent;
563  int i;
564 
565  memset(mvd.players, 0, sizeof(player_packed_t) * sv_maxclients->integer);
566  memset(mvd.entities, 0, sizeof(entity_packed_t) * MAX_EDICTS);
567 
568  // set base player states
569  for (i = 0; i < sv_maxclients->integer; i++) {
570  ent = EDICT_NUM(i + 1);
571 
572  if (!player_is_active(ent)) {
573  continue;
574  }
575 
576  MSG_PackPlayer(&mvd.players[i], &ent->client->ps);
577  PPS_INUSE(&mvd.players[i]) = qtrue;
578  }
579 
580  // set base entity states
581  for (i = 1; i < ge->num_edicts; i++) {
582  ent = EDICT_NUM(i);
583 
584  if (!entity_is_active(ent)) {
585  continue;
586  }
587 
588  MSG_PackEntity(&mvd.entities[i], &ent->s, qfalse);
589  mvd.entities[i].number = i;
590  }
591 }

Referenced by resume_streams(), and SV_MvdMapChanged().

◆ check_clients_activity()

static void check_clients_activity ( void  )
static

Definition at line 885 of file mvd.c.

886 {
887  unsigned delta = sv_mvd_disconnect_time->value * 60 * 1000;
888 
889  if (!delta || mvd.recording || !LIST_EMPTY(&gtv_active_list)) {
891  } else if (svs.realtime - mvd.clients_active > delta) {
892  mvd_disable();
893  }
894 }

Referenced by SV_MvdBeginFrame().

◆ check_players_activity()

static void check_players_activity ( void  )
static

Definition at line 897 of file mvd.c.

898 {
899  unsigned delta = sv_mvd_suspend_time->value * 60 * 1000;
900 
901  if (!delta || players_active()) {
903  if (!mvd.active) {
904  resume_streams();
905  }
906  } else if (mvd.active) {
907  if (svs.realtime - mvd.players_active > delta) {
908  suspend_streams();
909  }
910  }
911 }

Referenced by mvd_enable(), and SV_MvdBeginFrame().

◆ copy_entity_state()

static void copy_entity_state ( entity_packed_t *  dst,
const entity_packed_t *  src,
int  flags 
)
static

Definition at line 686 of file mvd.c.

687 {
688  if (!(flags & MSG_ES_FIRSTPERSON)) {
689  VectorCopy(src->origin, dst->origin);
690  VectorCopy(src->angles, dst->angles);
691  VectorCopy(src->old_origin, dst->old_origin);
692  }
693  dst->modelindex = src->modelindex;
694  dst->modelindex2 = src->modelindex2;
695  dst->modelindex3 = src->modelindex3;
696  dst->modelindex4 = src->modelindex4;
697  dst->frame = src->frame;
698  dst->skinnum = src->skinnum;
699  dst->effects = src->effects;
700  dst->renderfx = src->renderfx;
701  dst->solid = src->solid;
702  dst->sound = src->sound;
703  dst->event = 0;
704 }

Referenced by emit_frame().

◆ drop_client()

static void drop_client ( gtv_client_t client,
const char *  error 
)
static

Definition at line 1353 of file mvd.c.

1354 {
1355  if (client->state <= cs_zombie) {
1356  return;
1357  }
1358 
1359  if (error) {
1360  // notify console
1361  Com_Printf("TCP client %s[%s] dropped: %s\n", client->name,
1362  NET_AdrToString(&client->stream.address), error);
1363  }
1364 
1365 #if USE_ZLIB
1366  if (client->z.state) {
1367  // finish zlib stream
1368  flush_stream(client, Z_FINISH);
1369  deflateEnd(&client->z);
1370  }
1371 #endif
1372 
1373  List_Remove(&client->active);
1374  client->state = cs_zombie;
1375  client->lastmessage = svs.realtime;
1376 }

Referenced by mvd_drop(), parse_hello(), parse_message(), parse_stream_start(), parse_stream_stop(), parse_stringcmd(), SV_MvdRunClients(), and write_stream().

◆ dummy_add_message()

static void dummy_add_message ( client_t client,
byte *  data,
size_t  length,
qboolean  reliable 
)
static

Definition at line 272 of file mvd.c.

274 {
275  char *text;
276 
277  if (!length || !reliable || data[0] != svc_stufftext) {
278  return; // not interesting
279  }
280 
281  if (sv_mvd_allow_stufftext->integer <= 0) {
282  return; // not allowed
283  }
284 
285  data[length] = 0;
286  text = (char *)(data + 1);
287  Com_DPrintf("dummy stufftext: %s\n", text);
288  Cbuf_AddText(&dummy_buffer, text);
289 }

Referenced by dummy_create().

◆ dummy_command()

static void dummy_command ( void  )
static

Definition at line 150 of file mvd.c.

151 {
152  sv_client = mvd.dummy;
154  ge->ClientCommand(sv_player);
155  sv_client = NULL;
156  sv_player = NULL;
157 }

Referenced by dummy_exec_string(), dummy_forward_f(), and parse_stringcmd().

◆ dummy_create()

static int dummy_create ( void  )
static

Definition at line 342 of file mvd.c.

343 {
344  client_t *newcl;
345  char userinfo[MAX_INFO_STRING * 2];
346  char *s;
347  qboolean allow;
348  int number;
349 
350  // do nothing if already created
351  if (mvd.dummy)
352  return 0;
353 
354  if (sv_mvd_spawn_dummy->integer <= 0) {
355  Com_DPrintf("Dummy MVD client disabled\n");
356  return 0;
357  }
358 
359  if (sv_mvd_spawn_dummy->integer == 1 && !(g_features->integer & GMF_MVDSPEC)) {
360  Com_DPrintf("Dummy MVD client not supported by game\n");
361  return 0;
362  }
363 
364  // find a free client slot
365  newcl = dummy_find_slot();
366  if (!newcl) {
367  Com_EPrintf("No slot for dummy MVD client\n");
368  return -1;
369  }
370 
371  memset(newcl, 0, sizeof(*newcl));
372  number = newcl - svs.client_pool;
373  newcl->number = newcl->slot = number;
374  newcl->protocol = -1;
375  newcl->state = cs_connected;
376  newcl->AddMessage = dummy_add_message;
377  newcl->edict = EDICT_NUM(number + 1);
378  newcl->netchan = SV_Mallocz(sizeof(netchan_t));
379  newcl->netchan->remote_address.type = NA_LOOPBACK;
380 
381  List_Init(&newcl->entry);
382 
383  if (g_features->integer & GMF_EXTRA_USERINFO) {
384  strcpy(userinfo, MVD_USERINFO1);
385  strcpy(userinfo + strlen(userinfo) + 1, MVD_USERINFO2);
386  } else {
387  strcpy(userinfo, MVD_USERINFO1);
388  strcat(userinfo, MVD_USERINFO2);
389  userinfo[strlen(userinfo) + 1] = 0;
390  }
391 
392  mvd.dummy = newcl;
393 
394  // get the game a chance to reject this connection or modify the userinfo
395  sv_client = newcl;
396  sv_player = newcl->edict;
397  allow = ge->ClientConnect(newcl->edict, userinfo);
398  sv_client = NULL;
399  sv_player = NULL;
400  if (!allow) {
401  s = Info_ValueForKey(userinfo, "rejmsg");
402  if (!*s) {
403  s = "Connection refused";
404  }
405  Com_EPrintf("Dummy MVD client rejected by game: %s\n", s);
406  Z_Free(newcl->netchan);
407  mvd.dummy = NULL;
408  return -1;
409  }
410 
411  // parse some info from the info strings
412  Q_strlcpy(newcl->userinfo, userinfo, sizeof(newcl->userinfo));
413  SV_UserinfoChanged(newcl);
414 
415  return 1;
416 }

Referenced by mvd_enable(), and SV_MvdMapChanged().

◆ dummy_exec_string()

static void dummy_exec_string ( cmdbuf_t *  buf,
const char *  line 
)
static

Definition at line 229 of file mvd.c.

230 {
231  char *cmd, *alias;
232  const ucmd_t *u;
233  cvar_t *v;
234 
235  if (!line[0]) {
236  return;
237  }
238 
239  Cmd_TokenizeString(line, qtrue);
240 
241  cmd = Cmd_Argv(0);
242  if (!cmd[0]) {
243  return;
244  }
245  if ((u = Com_Find(dummy_cmds, cmd)) != NULL) {
246  if (u->func) {
247  u->func();
248  }
249  return;
250  }
251 
252  alias = Cmd_AliasCommand(cmd);
253  if (alias) {
254  if (++dummy_buffer.aliasCount == ALIAS_LOOP_COUNT) {
255  Com_WPrintf("%s: runaway alias loop\n", __func__);
256  return;
257  }
258  Cbuf_InsertText(&dummy_buffer, alias);
259  return;
260  }
261 
262  v = Cvar_FindVar(cmd);
263  if (v) {
264  Cvar_Command(v);
265  return;
266  }
267 
268  Com_DPrintf("dummy forward: %s\n", line);
269  dummy_command();
270 }

Referenced by SV_MvdInit().

◆ dummy_find_slot()

static client_t* dummy_find_slot ( void  )
static

Definition at line 311 of file mvd.c.

312 {
313  client_t *c;
314  int i, j;
315 
316  // first check if there is a free reserved slot
317  j = sv_maxclients->integer - sv_reserved_slots->integer;
318  for (i = j; i < sv_maxclients->integer; i++) {
319  c = &svs.client_pool[i];
320  if (!c->state) {
321  return c;
322  }
323  }
324 
325  // then check regular slots
326  for (i = 0; i < j; i++) {
327  c = &svs.client_pool[i];
328  if (!c->state) {
329  return c;
330  }
331  }
332 
333  return NULL;
334 }

Referenced by dummy_create().

◆ dummy_forward_f()

static void dummy_forward_f ( void  )
static

Definition at line 159 of file mvd.c.

160 {
161  Cmd_Shift();
162  Com_DPrintf("dummy cmd: %s %s\n", Cmd_Argv(0), Cmd_Args());
163  dummy_command();
164 }

◆ dummy_record_f()

static void dummy_record_f ( void  )
static

Definition at line 166 of file mvd.c.

167 {
168  char buffer[MAX_OSPATH];
169  qhandle_t f;
170 
171  if (!sv_mvd_autorecord->integer) {
172  return;
173  }
174 
175  if (Cmd_Argc() < 2) {
176  Com_Printf("Usage: %s <filename>\n", Cmd_Argv(0));
177  return;
178  }
179 
180  if (!rec_allowed()) {
181  return;
182  }
183 
184  f = FS_EasyOpenFile(buffer, sizeof(buffer), FS_MODE_WRITE,
185  "demos/", Cmd_Argv(1), ".mvd2");
186  if (!f) {
187  return;
188  }
189 
190  if (!mvd_enable()) {
191  FS_FCloseFile(f);
192  return;
193  }
194 
195  Com_Printf("Auto-recording local MVD to %s\n", buffer);
196 
197  rec_start(f);
198 }

◆ dummy_run()

static void dummy_run ( void  )
static

Definition at line 418 of file mvd.c.

419 {
420  usercmd_t cmd;
421 
422  if (!mvd.dummy)
423  return;
424 
426  if (dummy_buffer.waitCount > 0) {
427  dummy_buffer.waitCount--;
428  }
429 
430  // run ClientThink to prevent timeouts, etc
431  memset(&cmd, 0, sizeof(cmd));
432  cmd.msec = BASE_FRAMETIME;
433  sv_client = mvd.dummy;
435  ge->ClientThink(sv_player, &cmd);
436  sv_client = NULL;
437  sv_player = NULL;
438 
439  // check if the layout is constantly updated. if not,
440  // game mod has probably closed the scoreboard, open it again
441  if (mvd.active && sv_mvd_scorecmd->string[0]) {
442  if (svs.realtime - mvd.layout_time > 9000) {
445  }
446  }
447 }

Referenced by SV_MvdEndFrame().

◆ dummy_spawn()

static void dummy_spawn ( void  )
static

Definition at line 291 of file mvd.c.

292 {
293  if (!mvd.dummy)
294  return;
295 
296  sv_client = mvd.dummy;
298  ge->ClientBegin(sv_player);
299  sv_client = NULL;
300  sv_player = NULL;
301 
302  if (sv_mvd_begincmd->string[0]) {
304  }
305 
307 
309 }

Referenced by mvd_enable(), and SV_MvdMapChanged().

◆ dummy_stop_f()

static void dummy_stop_f ( void  )
static

Definition at line 200 of file mvd.c.

201 {
202  if (!sv_mvd_autorecord->integer) {
203  return;
204  }
205 
206  if (!mvd.recording) {
207  Com_Printf("Not recording a local MVD.\n");
208  return;
209  }
210 
211  Com_Printf("Stopped local MVD auto-recording.\n");
212  rec_stop();
213 }

◆ dummy_wait_f()

static void dummy_wait_f ( void  )
static

Definition at line 140 of file mvd.c.

141 {
142  int count = atoi(Cmd_Argv(1));
143 
144  if (count < 1) {
145  count = 1;
146  }
147  dummy_buffer.waitCount = count;
148 }

◆ dump_clients()

static void dump_clients ( void  )
static

Definition at line 1857 of file mvd.c.

1858 {
1859  gtv_client_t *client;
1860  int count;
1861 
1862  Com_Printf(
1863  "num name buf lastmsg address state\n"
1864  "--- ---------------- --- ------- --------------------- -----\n");
1865  count = 0;
1866  FOR_EACH_GTV(client) {
1867  Com_Printf("%3d %-16.16s %3"PRIz" %7u %-21s ",
1868  count, client->name, FIFO_Usage(&client->stream.send),
1869  svs.realtime - client->lastmessage,
1870  NET_AdrToString(&client->stream.address));
1871 
1872  switch (client->state) {
1873  case cs_zombie:
1874  Com_Printf("ZMBI ");
1875  break;
1876  case cs_assigned:
1877  Com_Printf("ASGN ");
1878  break;
1879  case cs_connected:
1880  Com_Printf("CNCT ");
1881  break;
1882  case cs_primed:
1883  Com_Printf("PRIM ");
1884  break;
1885  default:
1886  Com_Printf("SEND ");
1887  break;
1888  }
1889  Com_Printf("\n");
1890 
1891  count++;
1892  }
1893 }

Referenced by SV_MvdStatus_f().

◆ dump_versions()

static void dump_versions ( void  )
static

Definition at line 1895 of file mvd.c.

1896 {
1897  gtv_client_t *client;
1898  int count;
1899 
1900  Com_Printf(
1901  "num name version\n"
1902  "--- ---------------- -----------------------------------------\n");
1903 
1904  FOR_EACH_GTV(client) {
1905  count = 0;
1906  Com_Printf("%3i %-16.16s %-40.40s\n",
1907  count, client->name, client->version);
1908  count++;
1909  }
1910 }

Referenced by SV_MvdStatus_f().

◆ emit_frame()

static void emit_frame ( void  )
static

Definition at line 711 of file mvd.c.

712 {
713  player_packed_t *oldps, newps;
714  entity_packed_t *oldes, newes;
715  edict_t *ent;
716  int flags, portalbytes;
717  byte portalbits[MAX_MAP_PORTAL_BYTES];
718  int i;
719 
720  MSG_WriteByte(mvd_frame);
721 
722  // send portal bits
723  portalbytes = CM_WritePortalBits(&sv.cm, portalbits);
724  MSG_WriteByte(portalbytes);
725  MSG_WriteData(portalbits, portalbytes);
726 
727  flags = MSG_PS_IGNORE_PREDICTION | MSG_PS_IGNORE_DELTAANGLES;
728  if (sv_mvd_noblend->integer) {
729  flags |= MSG_PS_IGNORE_BLEND;
730  }
731  if (sv_mvd_nogun->integer) {
732  flags |= MSG_PS_IGNORE_GUNINDEX | MSG_PS_IGNORE_GUNFRAMES;
733  }
734 
735  // send player states
736  for (i = 0; i < sv_maxclients->integer; i++) {
737  oldps = &mvd.players[i];
738  ent = EDICT_NUM(i + 1);
739 
740  if (!player_is_active(ent)) {
741  if (PPS_INUSE(oldps)) {
742  // the old player isn't present in the new message
743  MSG_WriteDeltaPlayerstate_Packet(NULL, NULL, i, flags);
744  PPS_INUSE(oldps) = qfalse;
745  }
746  continue;
747  }
748 
749  // quantize
750  MSG_PackPlayer(&newps, &ent->client->ps);
751 
752  if (PPS_INUSE(oldps)) {
753  // delta update from old position
754  // because the force parm is false, this will not result
755  // in any bytes being emited if the player has not changed at all
756  MSG_WriteDeltaPlayerstate_Packet(oldps, &newps, i, flags);
757  } else {
758  // this is a new player, send it from the last state
759  MSG_WriteDeltaPlayerstate_Packet(oldps, &newps, i,
760  flags | MSG_PS_FORCE);
761  }
762 
763  // shuffle current state to previous
764  *oldps = newps;
765  PPS_INUSE(oldps) = qtrue;
766  }
767 
768  MSG_WriteByte(CLIENTNUM_NONE); // end of packetplayers
769 
770  // send entity states
771  for (i = 1; i < ge->num_edicts; i++) {
772  oldes = &mvd.entities[i];
773  ent = EDICT_NUM(i);
774 
775  if (!entity_is_active(ent)) {
776  if (oldes->number) {
777  // the old entity isn't present in the new message
778  MSG_WriteDeltaEntity(oldes, NULL, MSG_ES_FORCE);
779  oldes->number = 0;
780  }
781  continue;
782  }
783 
784  if (ent->s.number != i) {
785  Com_WPrintf("%s: fixing ent->s.number: %d to %d\n",
786  __func__, ent->s.number, i);
787  ent->s.number = i;
788  }
789 
790  // calculate flags
791  flags = MSG_ES_UMASK;
792  if (i <= sv_maxclients->integer) {
793  oldps = &mvd.players[i - 1];
794  if (PPS_INUSE(oldps) && oldps->pmove.pm_type == PM_NORMAL) {
795  // do not waste bandwidth on origin/angle updates,
796  // client will recover them from player state
797  flags |= MSG_ES_FIRSTPERSON;
798  }
799  }
800 
801  if (!oldes->number) {
802  // this is a new entity, send it from the last state
803  flags |= MSG_ES_FORCE | MSG_ES_NEWENTITY;
804  }
805 
806  // quantize
807  MSG_PackEntity(&newes, &ent->s, qfalse);
808 
809  MSG_WriteDeltaEntity(oldes, &newes, flags);
810 
811  // shuffle current state to previous
812  copy_entity_state(oldes, &newes, flags);
813  oldes->number = i;
814  }
815 
816  MSG_WriteShort(0); // end of packetentities
817 }

Referenced by SV_MvdEndFrame().

◆ emit_gamestate()

static void emit_gamestate ( void  )
static

Definition at line 595 of file mvd.c.

596 {
597  char *string;
598  int i, j;
599  player_packed_t *ps;
600  entity_packed_t *es;
601  size_t length;
602  int flags, extra, portalbytes;
603  byte portalbits[MAX_MAP_PORTAL_BYTES];
604 
605  // don't bother writing if there are no active MVD clients
606  if (!mvd.recording && LIST_EMPTY(&gtv_active_list)) {
607  return;
608  }
609 
610  // pack MVD stream flags into extra bits
611  extra = 0;
612  if (sv_mvd_nomsgs->integer && mvd.dummy) {
613  extra |= MVF_NOMSGS << SVCMD_BITS;
614  }
615 
616  // send the serverdata
617  MSG_WriteByte(mvd_serverdata | extra);
618  MSG_WriteLong(PROTOCOL_VERSION_MVD);
619  MSG_WriteShort(PROTOCOL_VERSION_MVD_CURRENT);
621  MSG_WriteString(fs_game->string);
622  if (mvd.dummy)
624  else
625  MSG_WriteShort(-1);
626 
627  // send configstrings
628  for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
629  string = sv.configstrings[i];
630  if (!string[0]) {
631  continue;
632  }
633  length = strlen(string);
634  if (length > MAX_QPATH) {
635  length = MAX_QPATH;
636  }
637 
638  MSG_WriteShort(i);
639  MSG_WriteData(string, length);
640  MSG_WriteByte(0);
641  }
642  MSG_WriteShort(MAX_CONFIGSTRINGS);
643 
644  // send baseline frame
645  portalbytes = CM_WritePortalBits(&sv.cm, portalbits);
646  MSG_WriteByte(portalbytes);
647  MSG_WriteData(portalbits, portalbytes);
648 
649  // send player states
650  flags = 0;
651  if (sv_mvd_noblend->integer) {
652  flags |= MSG_PS_IGNORE_BLEND;
653  }
654  if (sv_mvd_nogun->integer) {
655  flags |= MSG_PS_IGNORE_GUNINDEX | MSG_PS_IGNORE_GUNFRAMES;
656  }
657  for (i = 0, ps = mvd.players; i < sv_maxclients->integer; i++, ps++) {
658  extra = 0;
659  if (!PPS_INUSE(ps)) {
660  extra |= MSG_PS_REMOVE;
661  }
662  MSG_WriteDeltaPlayerstate_Packet(NULL, ps, i, flags | extra);
663  }
664  MSG_WriteByte(CLIENTNUM_NONE);
665 
666  // send entity states
667  for (i = 1, es = mvd.entities + 1; i < ge->num_edicts; i++, es++) {
668  flags = MSG_ES_UMASK;
669  if ((j = es->number) != 0) {
670  if (i <= sv_maxclients->integer) {
671  ps = &mvd.players[i - 1];
672  if (PPS_INUSE(ps) && ps->pmove.pm_type == PM_NORMAL) {
673  flags |= MSG_ES_FIRSTPERSON;
674  }
675  }
676  } else {
677  flags |= MSG_ES_REMOVE;
678  }
679  es->number = i;
680  MSG_WriteDeltaEntity(NULL, es, flags);
681  es->number = j;
682  }
683  MSG_WriteShort(0);
684 }

Referenced by parse_stream_start(), rec_start(), resume_streams(), and SV_MvdMapChanged().

◆ entity_is_active()

static qboolean entity_is_active ( const edict_t *  ent)
static

Definition at line 546 of file mvd.c.

547 {
548  if ((g_features->integer & GMF_PROPERINUSE) && !ent->inuse) {
549  return qfalse;
550  }
551 
552  if (ent->svflags & SVF_NOCLIENT) {
553  return qfalse;
554  }
555 
556  return ES_INUSE(&ent->s);
557 }

Referenced by build_gamestate(), and emit_frame().

◆ filter_unicast_data()

static qboolean filter_unicast_data ( edict_t *  ent)
static

Definition at line 1149 of file mvd.c.

1150 {
1151  int cmd = msg_write.data[0];
1152 
1153  // discard any stufftexts, except of play sound hacks
1154  if (cmd == svc_stufftext) {
1155  return !memcmp(msg_write.data + 1, "play ", 5);
1156  }
1157 
1158  // if there is no dummy client, don't discard anything
1159  if (!mvd.dummy) {
1160  return qtrue;
1161  }
1162 
1163  if (cmd == svc_layout) {
1164  if (ent != mvd.dummy->edict) {
1165  // discard any layout updates to players
1166  return qfalse;
1167  }
1169  } else if (cmd == svc_print) {
1170  if (ent != mvd.dummy->edict && sv_mvd_nomsgs->integer) {
1171  // optionally discard text messages to players
1172  return qfalse;
1173  }
1174  }
1175 
1176  return qtrue;
1177 }

Referenced by SV_MvdUnicast().

◆ find_slot()

static gtv_client_t* find_slot ( void  )
static

Definition at line 1713 of file mvd.c.

1714 {
1715  gtv_client_t *client;
1716  int i;
1717 
1718  for (i = 0; i < sv_mvd_maxclients->integer; i++) {
1719  client = &mvd.clients[i];
1720  if (!client->state) {
1721  return client;
1722  }
1723  }
1724 
1725  return NULL;
1726 }

Referenced by accept_client().

◆ LIST_DECL() [1/4]

static LIST_DECL ( gtv_active_list  )
static

◆ LIST_DECL() [2/4]

static LIST_DECL ( gtv_black_list  )
static

◆ LIST_DECL() [3/4]

static LIST_DECL ( gtv_client_list  )
static

◆ LIST_DECL() [4/4]

static LIST_DECL ( gtv_white_list  )
static

◆ mvd_disable()

static void mvd_disable ( void  )
static

Definition at line 940 of file mvd.c.

941 {
942  if (mvd.enabled)
943  Com_DPrintf("Disabling server MVD recorder.\n");
944 
945  // drop (no-op if already dropped) and remove MVD dummy. NULL out pointer
946  // before calling SV_DropClient to prevent spurious error message.
947  if (mvd.dummy) {
948  client_t *tmp = mvd.dummy;
949  mvd.dummy = NULL;
950  SV_DropClient(tmp, NULL);
951  SV_RemoveClient(tmp);
952  }
953 
955  SZ_Clear(&mvd.message);
956 
957  mvd.enabled = qfalse;
958  mvd.active = qfalse;
959 }

Referenced by check_clients_activity(), and mvd_error().

◆ mvd_drop()

static void mvd_drop ( gtv_serverop_t  op)
static

Definition at line 1926 of file mvd.c.

1927 {
1928  gtv_client_t *client;
1929 
1930  // drop GTV clients
1931  FOR_EACH_GTV(client) {
1932  switch (client->state) {
1933  case cs_spawned:
1934  case cs_primed:
1935  write_message(client, op);
1936  drop_client(client, NULL);
1937  NET_UpdateStream(&client->stream);
1938  break;
1939  default:
1940  drop_client(client, NULL);
1941  remove_client(client);
1942  break;
1943  }
1944  }
1945 
1946  // update I/O status
1947  NET_Sleep(0);
1948 
1949  // push error message
1950  FOR_EACH_GTV(client) {
1951  NET_RunStream(&client->stream);
1952  NET_RunStream(&client->stream);
1953  remove_client(client);
1954  }
1955 
1956  List_Init(&gtv_client_list);
1957  List_Init(&gtv_active_list);
1958 }

Referenced by mvd_error(), and SV_MvdShutdown().

◆ mvd_enable()

static qboolean mvd_enable ( void  )
static

Definition at line 913 of file mvd.c.

914 {
915  int ret;
916 
917  if (!mvd.enabled)
918  Com_DPrintf("Enabling server MVD recorder.\n");
919 
920  // create and spawn MVD dummy
921  ret = dummy_create();
922  if (ret < 0)
923  return qfalse;
924 
925  if (ret > 0)
926  dummy_spawn();
927 
928  // we are enabled now
929  mvd.enabled = qtrue;
930 
931  // don't timeout
933 
934  // check for activation
936 
937  return qtrue;
938 }

Referenced by dummy_record_f(), parse_stream_start(), and SV_MvdRecord_f().

◆ mvd_error()

static void mvd_error ( const char *  reason)
static

Definition at line 1961 of file mvd.c.

1962 {
1963  Com_EPrintf("Fatal MVD error: %s\n", reason);
1964 
1965  // stop recording
1966  rec_stop();
1967 
1968  mvd_drop(GTS_ERROR);
1969 
1970  mvd_disable();
1971 }

Referenced by SV_MvdClientDropped(), and SV_MvdEndFrame().

◆ parse_hello()

static void parse_hello ( gtv_client_t client)
static

Definition at line 1455 of file mvd.c.

1456 {
1457  char password[MAX_QPATH];
1458  int protocol, flags;
1459  size_t size;
1460  byte *data;
1461 
1462  if (client->state >= cs_primed) {
1463  drop_client(client, "duplicated hello message");
1464  return;
1465  }
1466 
1467  // client should have already consumed the magic
1468  if (FIFO_Usage(&client->stream.send)) {
1469  drop_client(client, "send buffer not empty");
1470  return;
1471  }
1472 
1473  protocol = MSG_ReadWord();
1474  if (protocol != GTV_PROTOCOL_VERSION) {
1475  write_message(client, GTS_BADREQUEST);
1476  drop_client(client, "bad protocol version");
1477  return;
1478  }
1479 
1480  flags = MSG_ReadLong();
1481  MSG_ReadLong();
1482  MSG_ReadString(client->name, sizeof(client->name));
1483  MSG_ReadString(password, sizeof(password));
1484  MSG_ReadString(client->version, sizeof(client->version));
1485 
1486  // authorize access
1487  if (!auth_client(client, password)) {
1488  write_message(client, GTS_NOACCESS);
1489  drop_client(client, "not authorized");
1490  return;
1491  }
1492 
1493  if (sv_mvd_allow_stufftext->integer >= 0) {
1494  flags &= ~GTF_STRINGCMDS;
1495  }
1496 
1497 #if !USE_ZLIB
1498  flags &= ~GTF_DEFLATE;
1499 #endif
1500 
1502 
1503  // allocate larger send buffer
1504  size = MAX_GTS_MSGLEN * sv_mvd_bufsize->integer;
1505  data = SV_Malloc(size);
1506  client->stream.send.data = data;
1507  client->stream.send.size = size;
1508  client->data = data;
1509  client->flags = flags;
1510  client->state = cs_primed;
1511 
1512  // send hello
1513  MSG_WriteLong(flags);
1514  write_message(client, GTS_HELLO);
1515  SZ_Clear(&msg_write);
1516 
1517 #if USE_ZLIB
1518  // the rest of the stream will be deflated
1519  if (flags & GTF_DEFLATE) {
1520  client->z.zalloc = SV_zalloc;
1521  client->z.zfree = SV_zfree;
1522  if (deflateInit(&client->z, Z_DEFAULT_COMPRESSION) != Z_OK) {
1523  drop_client(client, "deflateInit failed");
1524  return;
1525  }
1526  }
1527 #endif
1528 
1529  Com_Printf("Accepted MVD client %s[%s]\n", client->name,
1530  NET_AdrToString(&client->stream.address));
1531 }

Referenced by parse_message().

◆ parse_message()

static qboolean parse_message ( gtv_client_t client)
static

Definition at line 1632 of file mvd.c.

1633 {
1634  uint32_t magic;
1635  uint16_t msglen;
1636  int cmd;
1637 
1638  if (client->state <= cs_zombie) {
1639  return qfalse;
1640  }
1641 
1642  // check magic
1643  if (client->state < cs_connected) {
1644  if (!FIFO_TryRead(&client->stream.recv, &magic, 4)) {
1645  return qfalse;
1646  }
1647  if (magic != MVD_MAGIC) {
1648  drop_client(client, "not a MVD/GTV stream");
1649  return qfalse;
1650  }
1651  client->state = cs_connected;
1652 
1653  // send it back
1654  write_stream(client, &magic, 4);
1655  return qfalse;
1656  }
1657 
1658  // parse msglen
1659  if (!client->msglen) {
1660  if (!FIFO_TryRead(&client->stream.recv, &msglen, 2)) {
1661  return qfalse;
1662  }
1663  msglen = LittleShort(msglen);
1664  if (!msglen) {
1665  drop_client(client, "end of stream");
1666  return qfalse;
1667  }
1668  if (msglen > MAX_GTC_MSGLEN) {
1669  drop_client(client, "oversize message");
1670  return qfalse;
1671  }
1672  client->msglen = msglen;
1673  }
1674 
1675  // read this message
1676  if (!FIFO_ReadMessage(&client->stream.recv, client->msglen)) {
1677  return qfalse;
1678  }
1679 
1680  client->msglen = 0;
1681 
1682  cmd = MSG_ReadByte();
1683  switch (cmd) {
1684  case GTC_HELLO:
1685  parse_hello(client);
1686  break;
1687  case GTC_PING:
1688  parse_ping(client);
1689  break;
1690  case GTC_STREAM_START:
1691  parse_stream_start(client);
1692  break;
1693  case GTC_STREAM_STOP:
1694  parse_stream_stop(client);
1695  break;
1696  case GTC_STRINGCMD:
1697  parse_stringcmd(client);
1698  break;
1699  default:
1700  drop_client(client, "unknown command byte");
1701  return qfalse;
1702  }
1703 
1704  if (msg_read.readcount > msg_read.cursize) {
1705  drop_client(client, "read past end of message");
1706  return qfalse;
1707  }
1708 
1709  client->lastmessage = svs.realtime; // don't timeout
1710  return qtrue;
1711 }

Referenced by SV_MvdRunClients().

◆ parse_ping()

static void parse_ping ( gtv_client_t client)
static

Definition at line 1533 of file mvd.c.

1534 {
1535  if (client->state < cs_primed) {
1536  return;
1537  }
1538 
1539  // send ping reply
1540  write_message(client, GTS_PONG);
1541 
1542 #if USE_ZLIB
1543  flush_stream(client, Z_SYNC_FLUSH);
1544 #endif
1545 }

Referenced by parse_message().

◆ parse_stream_start()

static void parse_stream_start ( gtv_client_t client)
static

Definition at line 1547 of file mvd.c.

1548 {
1549  int maxbuf;
1550 
1551  if (client->state != cs_primed) {
1552  drop_client(client, "unexpected stream start message");
1553  return;
1554  }
1555 
1556  if (!mvd_enable()) {
1557  write_message(client, GTS_ERROR);
1558  drop_client(client, "couldn't create MVD dummy");
1559  return;
1560  }
1561 
1562  maxbuf = MSG_ReadShort();
1563  if (maxbuf < 10) {
1564  maxbuf = 10;
1565  }
1566 
1567  client->maxbuf = maxbuf;
1568  client->state = cs_spawned;
1569 
1570  List_Append(&gtv_active_list, &client->active);
1571 
1572  // send ack to client
1573  write_message(client, GTS_STREAM_START);
1574 
1575  // send gamestate if active
1576  if (mvd.active) {
1577  emit_gamestate();
1578  write_message(client, GTS_STREAM_DATA);
1579  SZ_Clear(&msg_write);
1580  } else {
1581  // send stream suspend marker
1582  write_message(client, GTS_STREAM_DATA);
1583  }
1584 
1585 #if USE_ZLIB
1586  flush_stream(client, Z_SYNC_FLUSH);
1587 #endif
1588 }

Referenced by parse_message().

◆ parse_stream_stop()

static void parse_stream_stop ( gtv_client_t client)
static

Definition at line 1590 of file mvd.c.

1591 {
1592  if (client->state != cs_spawned) {
1593  drop_client(client, "unexpected stream stop message");
1594  return;
1595  }
1596 
1597  client->state = cs_primed;
1598 
1599  List_Delete(&client->active);
1600 
1601  // send ack to client
1602  write_message(client, GTS_STREAM_STOP);
1603 #if USE_ZLIB
1604  flush_stream(client, Z_SYNC_FLUSH);
1605 #endif
1606 }

Referenced by parse_message().

◆ parse_stringcmd()

static void parse_stringcmd ( gtv_client_t client)
static

Definition at line 1608 of file mvd.c.

1609 {
1610  char string[MAX_GTC_MSGLEN];
1611 
1612  if (client->state < cs_primed) {
1613  drop_client(client, "unexpected stringcmd message");
1614  return;
1615  }
1616 
1617  if (!mvd.dummy || !(client->flags & GTF_STRINGCMDS)) {
1618  Com_DPrintf("ignored stringcmd from %s[%s]\n", client->name,
1619  NET_AdrToString(&client->stream.address));
1620  return;
1621  }
1622 
1623  MSG_ReadString(string, sizeof(string));
1624 
1625  Cmd_TokenizeString(string, qfalse);
1626 
1627  Com_DPrintf("dummy stringcmd from %s[%s]: %s\n", client->name,
1628  NET_AdrToString(&client->stream.address), string);
1629  dummy_command();
1630 }

Referenced by parse_message().

◆ player_is_active()

static qboolean player_is_active ( const edict_t *  ent)
static

Definition at line 479 of file mvd.c.

480 {
481  int num;
482 
483  if ((g_features->integer & GMF_PROPERINUSE) && !ent->inuse) {
484  return qfalse;
485  }
486 
487  // not a client at all?
488  if (!ent->client) {
489  return qfalse;
490  }
491 
492  num = NUM_FOR_EDICT(ent) - 1;
493  if (num < 0 || num >= sv_maxclients->integer) {
494  return qfalse;
495  }
496 
497  // by default, check if client is actually connected
498  // it may not be the case for bots!
499  if (sv_mvd_capture_flags->integer & 1) {
500  if (svs.client_pool[num].state != cs_spawned) {
501  return qfalse;
502  }
503  }
504 
505  // first of all, make sure player_state_t is valid
506  if (!ent->client->ps.fov) {
507  return qfalse;
508  }
509 
510  // always capture dummy MVD client
511  if (mvd.dummy && ent == mvd.dummy->edict) {
512  return qtrue;
513  }
514 
515  // never capture spectators
516  if (ent->client->ps.pmove.pm_type == PM_SPECTATOR) {
517  return qfalse;
518  }
519 
520  // check entity visibility
521  if ((ent->svflags & SVF_NOCLIENT) || !ES_INUSE(&ent->s)) {
522  // never capture invisible entities
523  if (sv_mvd_capture_flags->integer & 2) {
524  return qfalse;
525  }
526  } else {
527  // always capture visible entities (default)
528  if (sv_mvd_capture_flags->integer & 4) {
529  return qtrue;
530  }
531  }
532 
533  // they are likely following someone in case of PM_FREEZE
534  if (ent->client->ps.pmove.pm_type == PM_FREEZE) {
535  return qfalse;
536  }
537 
538  // they are likely following someone if PMF_NO_PREDICTION is set
539  if (ent->client->ps.pmove.pm_flags & PMF_NO_PREDICTION) {
540  return qfalse;
541  }
542 
543  return qtrue;
544 }

Referenced by build_gamestate(), emit_frame(), players_active(), and SV_MvdUnicast().

◆ players_active()

static qboolean players_active ( void  )
static

Definition at line 868 of file mvd.c.

869 {
870  int i;
871  edict_t *ent;
872 
873  for (i = 0; i < sv_maxclients->integer; i++) {
874  ent = EDICT_NUM(i + 1);
875  if (mvd.dummy && ent == mvd.dummy->edict)
876  continue;
877  if (player_is_active(ent))
878  return qtrue;
879  }
880 
881  return qfalse;
882 }

Referenced by check_players_activity().

◆ rec_allowed()

static qboolean rec_allowed ( void  )
static

Definition at line 2191 of file mvd.c.

2192 {
2193  if (!mvd.entities) {
2194  Com_Printf("MVD recording is disabled on this server.\n");
2195  return qfalse;
2196  }
2197 
2198  if (mvd.recording) {
2199  Com_Printf("Already recording a local MVD.\n");
2200  return qfalse;
2201  }
2202 
2203  return qtrue;
2204 }

Referenced by dummy_record_f(), and SV_MvdRecord_f().

◆ rec_frame()

static void rec_frame ( size_t  total)
static

Definition at line 961 of file mvd.c.

962 {
963  uint16_t msglen;
964  ssize_t ret;
965 
966  if (!total)
967  return;
968 
969  msglen = LittleShort(total);
970  ret = FS_Write(&msglen, 2, mvd.recording);
971  if (ret != 2)
972  goto fail;
973  ret = FS_Write(mvd.message.data, mvd.message.cursize, mvd.recording);
974  if (ret != mvd.message.cursize)
975  goto fail;
976  ret = FS_Write(msg_write.data, msg_write.cursize, mvd.recording);
977  if (ret != msg_write.cursize)
978  goto fail;
979  ret = FS_Write(mvd.datagram.data, mvd.datagram.cursize, mvd.recording);
980  if (ret != mvd.datagram.cursize)
981  goto fail;
982 
983  if (sv_mvd_maxsize->value > 0 &&
984  FS_Tell(mvd.recording) > sv_mvd_maxsize->value * 1000) {
985  Com_Printf("Stopping MVD recording, maximum size reached.\n");
986  rec_stop();
987  return;
988  }
989 
990  if (sv_mvd_maxtime->value > 0 &&
991  ++mvd.numframes > sv_mvd_maxtime->value * 600) {
992  Com_Printf("Stopping MVD recording, maximum duration reached.\n");
993  rec_stop();
994  return;
995  }
996 
997  return;
998 
999 fail:
1000  Com_EPrintf("Couldn't write local MVD: %s\n", Q_ErrorString(ret));
1001  rec_stop();
1002 }

Referenced by SV_MvdEndFrame().

◆ rec_start()

static void rec_start ( qhandle_t  demofile)
static

Definition at line 2206 of file mvd.c.

2207 {
2208  uint32_t magic;
2209 
2210  mvd.recording = demofile;
2211  mvd.numlevels = 0;
2212  mvd.numframes = 0;
2214 
2215  magic = MVD_MAGIC;
2216  FS_Write(&magic, 4, demofile);
2217 
2218  if (mvd.active) {
2219  emit_gamestate();
2220  rec_write();
2221  SZ_Clear(&msg_write);
2222  }
2223 }

Referenced by dummy_record_f(), and SV_MvdRecord_f().

◆ rec_stop()

static void rec_stop ( void  )
static

Definition at line 2175 of file mvd.c.

2176 {
2177  uint16_t msglen;
2178 
2179  if (!mvd.recording) {
2180  return;
2181  }
2182 
2183  // write demo EOF marker
2184  msglen = 0;
2185  FS_Write(&msglen, 2, mvd.recording);
2186 
2188  mvd.recording = 0;
2189 }

Referenced by dummy_stop_f(), mvd_error(), rec_frame(), rec_write(), SV_MvdMapChanged(), SV_MvdShutdown(), and SV_MvdStop_f().

◆ rec_write()

static void rec_write ( void  )
static

Definition at line 2153 of file mvd.c.

2154 {
2155  uint16_t msglen;
2156  ssize_t ret;
2157 
2158  if (!msg_write.cursize)
2159  return;
2160 
2161  msglen = LittleShort(msg_write.cursize);
2162  ret = FS_Write(&msglen, 2, mvd.recording);
2163  if (ret != 2)
2164  goto fail;
2165  ret = FS_Write(msg_write.data, msg_write.cursize, mvd.recording);
2166  if (ret == msg_write.cursize)
2167  return;
2168 
2169 fail:
2170  Com_EPrintf("Couldn't write local MVD: %s\n", Q_ErrorString(ret));
2171  rec_stop();
2172 }

Referenced by rec_start(), resume_streams(), and SV_MvdMapChanged().

◆ remove_client()

static void remove_client ( gtv_client_t client)
static

Definition at line 1302 of file mvd.c.

1303 {
1304  NET_CloseStream(&client->stream);
1305  List_Remove(&client->entry);
1306  if (client->data) {
1307  Z_Free(client->data);
1308  client->data = NULL;
1309  }
1310  client->state = cs_free;
1311 }

Referenced by mvd_drop(), and SV_MvdRunClients().

◆ resume_streams()

static void resume_streams ( void  )
static

Definition at line 836 of file mvd.c.

837 {
838  gtv_client_t *client;
839 
840  // build and emit gamestate
841  build_gamestate();
842  emit_gamestate();
843 
844  FOR_EACH_ACTIVE_GTV(client) {
845  // send gamestate
846  write_message(client, GTS_STREAM_DATA);
847 #if USE_ZLIB
848  flush_stream(client, Z_SYNC_FLUSH);
849 #endif
850  NET_UpdateStream(&client->stream);
851  }
852 
853  // write it to demofile
854  if (mvd.recording) {
855  rec_write();
856  }
857 
858  // clear gamestate
860 
862  SZ_Clear(&mvd.message);
863 
864  Com_DPrintf("Resuming MVD streams.\n");
865  mvd.active = qtrue;
866 }

Referenced by check_players_activity().

◆ suspend_streams()

static void suspend_streams ( void  )
static

Definition at line 819 of file mvd.c.

820 {
821  gtv_client_t *client;
822 
823  FOR_EACH_ACTIVE_GTV(client) {
824  // send stream suspend marker
825  write_message(client, GTS_STREAM_DATA);
826 #if USE_ZLIB
827  flush_stream(client, Z_SYNC_FLUSH);
828 #endif
829  NET_UpdateStream(&client->stream);
830  }
831 
832  Com_DPrintf("Suspending MVD streams.\n");
833  mvd.active = qfalse;
834 }

Referenced by check_players_activity().

◆ SV_AddGtvBan_f()

static void SV_AddGtvBan_f ( void  )
static

Definition at line 2339 of file mvd.c.

2340 {
2341  SV_AddMatch_f(&gtv_black_list);
2342 }

◆ SV_AddGtvHost_f()

static void SV_AddGtvHost_f ( void  )
static

Definition at line 2326 of file mvd.c.

2327 {
2328  SV_AddMatch_f(&gtv_white_list);
2329 }

◆ SV_DelGtvBan_f()

static void SV_DelGtvBan_f ( void  )
static

Definition at line 2343 of file mvd.c.

2344 {
2345  SV_DelMatch_f(&gtv_black_list);
2346 }

◆ SV_DelGtvHost_f()

static void SV_DelGtvHost_f ( void  )
static

Definition at line 2330 of file mvd.c.

2331 {
2332  SV_DelMatch_f(&gtv_white_list);
2333 }

◆ SV_ListGtvBans_f()

static void SV_ListGtvBans_f ( void  )
static

Definition at line 2347 of file mvd.c.

2348 {
2349  SV_ListMatches_f(&gtv_black_list);
2350 }

◆ SV_ListGtvHosts_f()

static void SV_ListGtvHosts_f ( void  )
static

Definition at line 2334 of file mvd.c.

2335 {
2336  SV_ListMatches_f(&gtv_white_list);
2337 }

◆ SV_MvdBeginFrame()

void SV_MvdBeginFrame ( void  )

Definition at line 1009 of file mvd.c.

1010 {
1011  if (mvd.enabled)
1013 
1014  if (mvd.enabled)
1016 }

Referenced by SV_RunGameFrame().

◆ SV_MvdBroadcastPrint()

void SV_MvdBroadcastPrint ( int  level,
const char *  string 
)

Definition at line 1241 of file mvd.c.

1242 {
1243  if (mvd.active) {
1244  SZ_WriteByte(&mvd.message, mvd_print);
1246  SZ_WriteString(&mvd.message, string);
1247  }
1248 }

Referenced by PF_bprintf().

◆ SV_MvdClientDropped()

void SV_MvdClientDropped ( client_t client)

Definition at line 2054 of file mvd.c.

2055 {
2056  if (client == mvd.dummy) {
2057  mvd_error("dummy client was dropped");
2058  }
2059 }

Referenced by SV_DropClient().

◆ SV_MvdConfigstring()

void SV_MvdConfigstring ( int  index,
const char *  string,
size_t  len 
)

Definition at line 1226 of file mvd.c.

1227 {
1228  if (mvd.active) {
1229  SZ_WriteByte(&mvd.message, mvd_configstring);
1230  SZ_WriteShort(&mvd.message, index);
1231  SZ_Write(&mvd.message, string, len);
1232  SZ_WriteByte(&mvd.message, 0);
1233  }
1234 }

Referenced by PF_configstring().

◆ SV_MvdEndFrame()

void SV_MvdEndFrame ( void  )

Definition at line 1023 of file mvd.c.

1024 {
1025  gtv_client_t *client;
1026  size_t total;
1027  byte header[3];
1028 
1029  if (!SV_FRAMESYNC)
1030  return;
1031 
1032  // do nothing if not enabled
1033  if (!mvd.enabled) {
1034  return;
1035  }
1036 
1037  dummy_run();
1038 
1039  // do nothing if not active
1040  if (!mvd.active) {
1041  return;
1042  }
1043 
1044  // if reliable message overflowed, kick all clients
1045  if (mvd.message.overflowed) {
1046  mvd_error("reliable message overflowed");
1047  return;
1048  }
1049 
1050  if (mvd.datagram.overflowed) {
1051  Com_WPrintf("Unreliable MVD datagram overflowed.\n");
1052  SZ_Clear(&mvd.datagram);
1053  }
1054 
1055  // emit a delta update common to all clients
1056  emit_frame();
1057 
1058  // if reliable message and frame update don't fit, kick all clients
1059  if (mvd.message.cursize + msg_write.cursize >= MAX_MSGLEN) {
1060  SZ_Clear(&msg_write);
1061  mvd_error("frame overflowed");
1062  return;
1063  }
1064 
1065  // check if unreliable datagram fits
1066  if (mvd.message.cursize + msg_write.cursize + mvd.datagram.cursize >= MAX_MSGLEN) {
1067  Com_WPrintf("Dumping unreliable MVD datagram.\n");
1068  SZ_Clear(&mvd.datagram);
1069  }
1070 
1071  // build message header
1072  total = mvd.message.cursize + msg_write.cursize + mvd.datagram.cursize + 1;
1073  header[0] = total & 255;
1074  header[1] = (total >> 8) & 255;
1075  header[2] = GTS_STREAM_DATA;
1076 
1077  // send frame to clients
1078  FOR_EACH_ACTIVE_GTV(client) {
1079  write_stream(client, header, sizeof(header));
1080  write_stream(client, mvd.message.data, mvd.message.cursize);
1081  write_stream(client, msg_write.data, msg_write.cursize);
1082  write_stream(client, mvd.datagram.data, mvd.datagram.cursize);
1083 #if USE_ZLIB
1084  if (++client->bufcount > client->maxbuf) {
1085  flush_stream(client, Z_SYNC_FLUSH);
1086  }
1087 #endif
1088  NET_UpdateStream(&client->stream);
1089  }
1090 
1091  // write frame to demofile
1092  if (mvd.recording) {
1093  rec_frame(total - 1);
1094  }
1095 
1096  // clear frame
1097  SZ_Clear(&msg_write);
1098 
1099  // clear datagrams
1100  SZ_Clear(&mvd.datagram);
1101  SZ_Clear(&mvd.message);
1102 }

Referenced by SV_RunGameFrame().

◆ SV_MvdInit()

void SV_MvdInit ( void  )

Definition at line 2068 of file mvd.c.

2069 {
2070  if (!sv_mvd_enable->integer) {
2071  return; // do nothing if disabled
2072  }
2073 
2074  // allocate buffers
2075  Z_TagReserve(sizeof(player_packed_t) * sv_maxclients->integer +
2076  sizeof(entity_packed_t) * MAX_EDICTS + MAX_MSGLEN * 2, TAG_SERVER);
2077  SZ_Init(&mvd.message, Z_ReservedAlloc(MAX_MSGLEN), MAX_MSGLEN);
2078  SZ_Init(&mvd.datagram, Z_ReservedAlloc(MAX_MSGLEN), MAX_MSGLEN);
2079  mvd.players = Z_ReservedAlloc(sizeof(player_packed_t) * sv_maxclients->integer);
2080  mvd.entities = Z_ReservedAlloc(sizeof(entity_packed_t) * MAX_EDICTS);
2081 
2082  // reserve the slot for dummy MVD client
2083  if (!sv_reserved_slots->integer) {
2084  Cvar_Set("sv_reserved_slots", "1");
2085  }
2086 
2088 
2089  // open server TCP socket
2090  if (sv_mvd_enable->integer > 1) {
2091  neterr_t ret;
2092 
2093  ret = NET_Listen(qtrue);
2094  if (ret == NET_OK) {
2095  mvd.clients = SV_Mallocz(sizeof(gtv_client_t) * sv_mvd_maxclients->integer);
2096  } else {
2097  if (ret == NET_ERROR)
2098  Com_EPrintf("%s while opening server TCP port.\n", NET_ErrorString());
2099  else
2100  Com_EPrintf("Server TCP port already in use.\n");
2101  Cvar_Set("sv_mvd_enable", "1");
2102  }
2103  }
2104 
2105  dummy_buffer.from = FROM_CONSOLE;
2107  dummy_buffer.maxsize = sizeof(dummy_buffer_text);
2109 }

Referenced by SV_InitGame().

◆ SV_MvdMapChanged()

void SV_MvdMapChanged ( void  )

Definition at line 1990 of file mvd.c.

1991 {
1992  gtv_client_t *client;
1993  int ret;
1994 
1995  if (!mvd.entities) {
1996  return; // do nothing if disabled
1997  }
1998 
1999  // spawn MVD dummy now if listening for autorecord command
2000  if (sv_mvd_autorecord->integer) {
2001  ret = dummy_create();
2002  if (ret < 0) {
2003  return;
2004  }
2005  if (ret > 0) {
2006  Com_DPrintf("Spawning MVD dummy for auto-recording\n");
2007  Cvar_Set("sv_mvd_suspend_time", "0");
2008  }
2009  }
2010 
2011  dummy_spawn();
2012 
2013  if (mvd.active) {
2014  // build and emit gamestate
2015  build_gamestate();
2016  emit_gamestate();
2017 
2018  // send gamestate to all MVD clients
2019  FOR_EACH_ACTIVE_GTV(client) {
2020  write_message(client, GTS_STREAM_DATA);
2021  NET_UpdateStream(&client->stream);
2022  }
2023  }
2024 
2025  if (mvd.recording) {
2026  int maxlevels = sv_mvd_maxmaps->integer;
2027 
2028  // check if it is time to stop recording
2029  if (maxlevels > 0 && ++mvd.numlevels >= maxlevels) {
2030  Com_Printf("Stopping MVD recording, "
2031  "maximum number of level changes reached.\n");
2032  rec_stop();
2033  } else if (mvd.active) {
2034  // write gamestate to demofile
2035  rec_write();
2036  }
2037  }
2038 
2039  // clear gamestate
2040  SZ_Clear(&msg_write);
2041 
2042  SZ_Clear(&mvd.datagram);
2043  SZ_Clear(&mvd.message);
2044 }

Referenced by SV_SpawnServer().

◆ SV_MvdMulticast()

void SV_MvdMulticast ( int  leafnum,
multicast_t  to 
)

Definition at line 1122 of file mvd.c.

1123 {
1124  mvd_ops_t op;
1125  sizebuf_t *buf;
1126  int bits;
1127 
1128  // do nothing if not active
1129  if (!mvd.active) {
1130  return;
1131  }
1132 
1133  op = mvd_multicast_all + to;
1134  buf = to < MULTICAST_ALL_R ? &mvd.datagram : &mvd.message;
1135  bits = (msg_write.cursize >> 8) & 7;
1136 
1137  SZ_WriteByte(buf, op | (bits << SVCMD_BITS));
1138  SZ_WriteByte(buf, msg_write.cursize & 255);
1139 
1140  if (op != mvd_multicast_all && op != mvd_multicast_all_r) {
1141  SZ_WriteShort(buf, leafnum);
1142  }
1143 
1144  SZ_Write(buf, msg_write.data, msg_write.cursize);
1145 }

Referenced by SV_Multicast().

◆ SV_MvdRecord_f()

void SV_MvdRecord_f ( void  )

Definition at line 2233 of file mvd.c.

2234 {
2235  char buffer[MAX_OSPATH];
2236  qhandle_t f;
2237  unsigned mode = FS_MODE_WRITE;
2238  int c;
2239 
2240  if (sv.state != ss_game) {
2241  Com_Printf("No server running.\n");
2242  return;
2243  }
2244 
2245  while ((c = Cmd_ParseOptions(o_record)) != -1) {
2246  switch (c) {
2247  case 'h':
2248  Cmd_PrintUsage(o_record, "<filename>");
2249  Com_Printf("Begin local MVD recording.\n");
2251  return;
2252  case 'z':
2253  mode |= FS_FLAG_GZIP;
2254  break;
2255  default:
2256  return;
2257  }
2258  }
2259 
2260  if (!cmd_optarg[0]) {
2261  Com_Printf("Missing filename argument.\n");
2262  Cmd_PrintHint();
2263  return;
2264  }
2265 
2266  if (!rec_allowed()) {
2267  return;
2268  }
2269 
2270  //
2271  // open the demo file
2272  //
2273  f = FS_EasyOpenFile(buffer, sizeof(buffer), mode,
2274  "demos/", cmd_optarg, ".mvd2");
2275  if (!f) {
2276  return;
2277  }
2278 
2279  if (!mvd_enable()) {
2280  FS_FCloseFile(f);
2281  return;
2282  }
2283 
2284  Com_Printf("Recording local MVD to %s\n", buffer);
2285 
2286  rec_start(f);
2287 }

◆ SV_MvdRegister()

void SV_MvdRegister ( void  )

Definition at line 2364 of file mvd.c.

2365 {
2366  sv_mvd_enable = Cvar_Get("sv_mvd_enable", "0", CVAR_LATCH);
2367  sv_mvd_maxclients = Cvar_Get("sv_mvd_maxclients", "8", CVAR_LATCH);
2368  sv_mvd_bufsize = Cvar_Get("sv_mvd_bufsize", "2", CVAR_LATCH);
2369  sv_mvd_password = Cvar_Get("sv_mvd_password", "", CVAR_PRIVATE);
2370  sv_mvd_maxsize = Cvar_Get("sv_mvd_maxsize", "0", 0);
2371  sv_mvd_maxtime = Cvar_Get("sv_mvd_maxtime", "0", 0);
2372  sv_mvd_maxmaps = Cvar_Get("sv_mvd_maxmaps", "1", 0);
2373  sv_mvd_noblend = Cvar_Get("sv_mvd_noblend", "0", CVAR_LATCH);
2374  sv_mvd_nogun = Cvar_Get("sv_mvd_nogun", "1", CVAR_LATCH);
2375  sv_mvd_nomsgs = Cvar_Get("sv_mvd_nomsgs", "1", CVAR_LATCH);
2376  sv_mvd_begincmd = Cvar_Get("sv_mvd_begincmd",
2377  "wait 50; putaway; wait 10; help;", 0);
2378  sv_mvd_scorecmd = Cvar_Get("sv_mvd_scorecmd",
2379  "putaway; wait 10; help;", 0);
2380  sv_mvd_autorecord = Cvar_Get("sv_mvd_autorecord", "0", CVAR_LATCH);
2381  sv_mvd_capture_flags = Cvar_Get("sv_mvd_capture_flags", "5", 0);
2382  sv_mvd_disconnect_time = Cvar_Get("sv_mvd_disconnect_time", "15", 0);
2383  sv_mvd_suspend_time = Cvar_Get("sv_mvd_suspend_time", "5", 0);
2384  sv_mvd_allow_stufftext = Cvar_Get("sv_mvd_allow_stufftext", "0", CVAR_LATCH);
2385  sv_mvd_spawn_dummy = Cvar_Get("sv_mvd_spawn_dummy", "1", 0);
2386 
2388 }

Referenced by SV_Init().

◆ SV_MvdRunClients()

void SV_MvdRunClients ( void  )

Definition at line 1783 of file mvd.c.

1784 {
1785  gtv_client_t *client;
1786  neterr_t ret;
1787  netstream_t stream;
1788  unsigned zombie_time = 1000 * sv_zombietime->value;
1789  unsigned drop_time = 1000 * sv_timeout->value;
1790  unsigned ghost_time = 1000 * sv_ghostime->value;
1791  unsigned delta;
1792 
1793  if (!mvd.clients) {
1794  return; // do nothing if disabled
1795  }
1796 
1797  // accept new connections
1798  ret = NET_Accept(&stream);
1799  if (ret == NET_ERROR) {
1800  Com_DPrintf("%s from %s, ignored\n", NET_ErrorString(),
1802  } else if (ret == NET_OK) {
1803  accept_client(&stream);
1804  }
1805 
1806  // run existing connections
1807  FOR_EACH_GTV(client) {
1808  // check timeouts
1809  delta = svs.realtime - client->lastmessage;
1810  switch (client->state) {
1811  case cs_zombie:
1812  if (delta > zombie_time || !FIFO_Usage(&client->stream.send)) {
1813  remove_client(client);
1814  continue;
1815  }
1816  break;
1817  case cs_assigned:
1818  case cs_connected:
1819  if (delta > ghost_time || delta > drop_time) {
1820  drop_client(client, "request timed out");
1821  remove_client(client);
1822  continue;
1823  }
1824  break;
1825  default:
1826  if (delta > drop_time) {
1827  drop_client(client, "connection timed out");
1828  remove_client(client);
1829  continue;
1830  }
1831  break;
1832  }
1833 
1834  // run network stream
1835  ret = NET_RunStream(&client->stream);
1836  switch (ret) {
1837  case NET_AGAIN:
1838  break;
1839  case NET_OK:
1840  // parse the message
1841  while (parse_message(client))
1842  ;
1843  NET_UpdateStream(&client->stream);
1844  break;
1845  case NET_CLOSED:
1846  drop_client(client, "EOF from client");
1847  remove_client(client);
1848  break;
1849  case NET_ERROR:
1850  drop_client(client, "connection reset by peer");
1851  remove_client(client);
1852  break;
1853  }
1854  }
1855 }

Referenced by SV_Frame().

◆ SV_MvdShutdown()

void SV_MvdShutdown ( error_type_t  type)

Definition at line 2118 of file mvd.c.

2119 {
2120  // stop recording
2121  rec_stop();
2122 
2123  // remove MVD dummy
2124  if (mvd.dummy) {
2126  mvd.dummy = NULL;
2127  }
2128 
2129  memset(&dummy_buffer, 0, sizeof(dummy_buffer));
2130 
2131  // drop all clients
2132  mvd_drop(type == ERR_RECONNECT ? GTS_RECONNECT : GTS_DISCONNECT);
2133 
2134  // free static data
2135  Z_Free(mvd.message.data);
2136  Z_Free(mvd.clients);
2137 
2138  // close server TCP socket
2139  NET_Listen(qfalse);
2140 
2141  memset(&mvd, 0, sizeof(mvd));
2142 }

Referenced by SV_Shutdown().

◆ SV_MvdStartSound()

void SV_MvdStartSound ( int  entnum,
int  channel,
int  flags,
int  soundindex,
int  volume,
int  attenuation,
int  timeofs 
)

Definition at line 1257 of file mvd.c.

1260 {
1261  int extrabits, sendchan;
1262 
1263  // do nothing if not active
1264  if (!mvd.active) {
1265  return;
1266  }
1267 
1268  extrabits = 0;
1269  if (channel & CHAN_NO_PHS_ADD) {
1270  extrabits |= 1 << SVCMD_BITS;
1271  }
1272  if (channel & CHAN_RELIABLE) {
1273  // FIXME: write to mvd.message
1274  extrabits |= 2 << SVCMD_BITS;
1275  }
1276 
1277  SZ_WriteByte(&mvd.datagram, mvd_sound | extrabits);
1278  SZ_WriteByte(&mvd.datagram, flags);
1279  SZ_WriteByte(&mvd.datagram, soundindex);
1280 
1281  if (flags & SND_VOLUME)
1282  SZ_WriteByte(&mvd.datagram, volume);
1283  if (flags & SND_ATTENUATION)
1284  SZ_WriteByte(&mvd.datagram, attenuation);
1285  if (flags & SND_OFFSET)
1286  SZ_WriteByte(&mvd.datagram, timeofs);
1287 
1288  sendchan = (entnum << 3) | (channel & 7);
1289  SZ_WriteShort(&mvd.datagram, sendchan);
1290 }

Referenced by PF_StartSound().

◆ SV_MvdStatus_f()

void SV_MvdStatus_f ( void  )

Definition at line 1912 of file mvd.c.

1913 {
1914  if (LIST_EMPTY(&gtv_client_list)) {
1915  Com_Printf("No TCP clients.\n");
1916  } else {
1917  if (Cmd_Argc() > 1) {
1918  dump_versions();
1919  } else {
1920  dump_clients();
1921  }
1922  }
1923  Com_Printf("\n");
1924 }

Referenced by SV_Status_f().

◆ SV_MvdStop_f()

void SV_MvdStop_f ( void  )

Definition at line 2297 of file mvd.c.

2298 {
2299  if (!mvd.recording) {
2300  Com_Printf("Not recording a local MVD.\n");
2301  return;
2302  }
2303 
2304  Com_Printf("Stopped local MVD recording.\n");
2305  rec_stop();
2306 }

◆ SV_MvdStuff_f()

static void SV_MvdStuff_f ( void  )
static

Definition at line 2316 of file mvd.c.

2317 {
2318  if (mvd.dummy) {
2320  Cbuf_AddText(&dummy_buffer, "\n");
2321  } else {
2322  Com_Printf("Can't '%s', dummy MVD client is not active\n", Cmd_Argv(0));
2323  }
2324 }

◆ SV_MvdUnicast()

void SV_MvdUnicast ( edict_t *  ent,
int  clientNum,
qboolean  reliable 
)

Definition at line 1184 of file mvd.c.

1185 {
1186  mvd_ops_t op;
1187  sizebuf_t *buf;
1188  int bits;
1189 
1190  // do nothing if not active
1191  if (!mvd.active) {
1192  return;
1193  }
1194 
1195  // discard any data to players not in the game
1196  if (!player_is_active(ent)) {
1197  return;
1198  }
1199 
1200  if (!filter_unicast_data(ent)) {
1201  return;
1202  }
1203 
1204  // decide where should it go
1205  if (reliable) {
1206  op = mvd_unicast_r;
1207  buf = &mvd.message;
1208  } else {
1209  op = mvd_unicast;
1210  buf = &mvd.datagram;
1211  }
1212 
1213  // write it
1214  bits = (msg_write.cursize >> 8) & 7;
1215  SZ_WriteByte(buf, op | (bits << SVCMD_BITS));
1216  SZ_WriteByte(buf, msg_write.cursize & 255);
1217  SZ_WriteByte(buf, clientNum);
1218  SZ_Write(buf, msg_write.data, msg_write.cursize);
1219 }

Referenced by PF_cprintf(), and PF_Unicast().

◆ write_message()

static void write_message ( gtv_client_t client,
gtv_serverop_t  op 
)
static

Definition at line 1427 of file mvd.c.

1428 {
1429  byte header[3];
1430  size_t len = msg_write.cursize + 1;
1431 
1432  header[0] = len & 255;
1433  header[1] = (len >> 8) & 255;
1434  header[2] = op;
1435  write_stream(client, header, sizeof(header));
1436 
1437  write_stream(client, msg_write.data, msg_write.cursize);
1438 }

Referenced by mvd_drop(), parse_hello(), parse_ping(), parse_stream_start(), parse_stream_stop(), resume_streams(), suspend_streams(), and SV_MvdMapChanged().

◆ write_stream()

static void write_stream ( gtv_client_t client,
void data,
size_t  len 
)
static

Definition at line 1379 of file mvd.c.

1380 {
1381  fifo_t *fifo = &client->stream.send;
1382 
1383  if (client->state <= cs_zombie) {
1384  return;
1385  }
1386 
1387  if (!len) {
1388  return;
1389  }
1390 
1391 #if USE_ZLIB
1392  if (client->z.state) {
1393  z_streamp z = &client->z;
1394 
1395  z->next_in = data;
1396  z->avail_in = (uInt)len;
1397 
1398  do {
1399  data = FIFO_Reserve(fifo, &len);
1400  if (!len) {
1401  drop_client(client, "overflowed");
1402  return;
1403  }
1404 
1405  z->next_out = data;
1406  z->avail_out = (uInt)len;
1407 
1408  if (deflate(z, Z_NO_FLUSH) != Z_OK) {
1409  drop_client(client, "deflate() failed");
1410  return;
1411  }
1412 
1413  len -= z->avail_out;
1414  if (len) {
1415  FIFO_Commit(fifo, len);
1416  client->bufcount = 0;
1417  }
1418  } while (z->avail_in);
1419  } else
1420 #endif
1421 
1422  if (FIFO_Write(fifo, data, len) != len) {
1423  drop_client(client, "overflowed");
1424  }
1425 }

Referenced by parse_message(), SV_MvdEndFrame(), and write_message().

Variable Documentation

◆ c_svmvd

const cmdreg_t c_svmvd[]
static
Initial value:
= {
{ "mvdstuff", SV_MvdStuff_f },
{ "addgtvhost", SV_AddGtvHost_f },
{ "delgtvhost", SV_DelGtvHost_f },
{ "listgtvhosts", SV_ListGtvHosts_f },
{ "addgtvban", SV_AddGtvBan_f },
{ "delgtvban", SV_DelGtvBan_f },
{ "listgtvbans", SV_ListGtvBans_f },
{ NULL }
}

Definition at line 2352 of file mvd.c.

Referenced by SV_MvdRegister().

◆ dummy_buffer

cmdbuf_t dummy_buffer
static

◆ dummy_buffer_text

char dummy_buffer_text[MAX_STRING_CHARS]
static

Definition at line 138 of file mvd.c.

Referenced by SV_MvdInit().

◆ dummy_cmds

const ucmd_t dummy_cmds[]
static
Initial value:
= {
{ "cmd", dummy_forward_f },
{ "set", Cvar_Set_f },
{ "alias", Cmd_Alias_f },
{ "play", NULL },
{ "stopsound", NULL },
{ "exec", NULL },
{ "screenshot", NULL },
{ "wait", dummy_wait_f },
{ "record", dummy_record_f },
{ "stop", dummy_stop_f },
{ NULL, NULL }
}

Definition at line 215 of file mvd.c.

Referenced by dummy_exec_string().

◆ mvd

mvd_server_t mvd
static

Definition at line 81 of file mvd.c.

Referenced by build_gamestate(), check_clients_activity(), check_players_activity(), count_chase_bits(), create_channel(), demo_destroy(), demo_emit_snapshot(), demo_find_snapshot(), demo_read_frame(), dummy_command(), dummy_create(), dummy_run(), dummy_spawn(), dummy_stop_f(), emit_base_frame(), emit_frame(), emit_gamestate(), entity_flags(), filter_unicast_data(), find_slot(), gtv_destroy(), gtv_forward_cmd(), gtv_oob_kill(), gtv_read_frame(), gtv_wait_start(), gtv_wait_stop(), list_generic(), list_recordings(), MVD_AutoFollow_f(), MVD_BroadcastPrintf(), MVD_ChangeLevel(), mvd_channel_list_f(), MVD_ClearState(), MVD_Control_f(), MVD_CountClients(), MVD_Destroy(), MVD_Destroyf(), mvd_disable(), mvd_enable(), MVD_Follow_f(), MVD_FollowNext(), MVD_FollowPrev(), MVD_FollowStop(), MVD_Forward_f(), MVD_Free(), MVD_GameClientBegin(), MVD_GameClientConnect(), MVD_GameInit(), MVD_GameRunFrame(), MVD_HitPlayer(), MVD_IntermissionStart(), MVD_IntermissionStop(), MVD_Invuse_f(), MVD_Join_f(), MVD_Kill_f(), MVD_LayoutChannels(), MVD_LayoutClients(), MVD_LayoutFollow(), MVD_LayoutScores(), MVD_LinkEdict(), MVD_MostFollowed(), MVD_NotifyClient(), MVD_Observe_f(), MVD_ParseConfigstring(), MVD_ParseEntityString(), MVD_ParseFrame(), MVD_ParseMessage(), MVD_ParseMulticast(), MVD_ParsePacketEntities(), MVD_ParsePacketPlayers(), MVD_ParsePrint(), MVD_ParseServerData(), MVD_ParseSound(), MVD_ParseUnicast(), MVD_Pause_f(), MVD_Play_f(), MVD_PlayerToEntityStates(), MVD_PrepWorldFrame(), MVD_Say_f(), MVD_Seek_f(), MVD_SetChannel(), MVD_SetDefaultLayout(), MVD_SetPlayer(), MVD_SetPlayerNames(), MVD_SetServerState(), MVD_Shutdown(), MVD_Skip_f(), MVD_StopRecord(), MVD_StreamedRecord_f(), MVD_StreamedStop_f(), MVD_SwitchChannel(), MVD_TestTarget(), MVD_TrySwitchChannel(), MVD_UnicastLayout(), MVD_UnicastPrint(), MVD_UnicastSend(), MVD_UnicastString(), MVD_UnicastStuff(), MVD_UpdateClient(), MVD_UpdateClients(), MVD_UpdateConfigstring(), MVD_UpdateLayouts(), MVD_UpdateTarget(), MVD_WriteDemoMessage(), parse_stream_data(), parse_stream_start(), parse_stringcmd(), player_is_active(), players_active(), print_channel(), rec_allowed(), rec_frame(), rec_start(), rec_stop(), rec_write(), reset_unicast_strings(), resume_streams(), set_player_name(), suspend_streams(), SV_MvdBeginFrame(), SV_MvdBroadcastPrint(), SV_MvdClientDropped(), SV_MvdConfigstring(), SV_MvdEndFrame(), SV_MvdInit(), SV_MvdMapChanged(), SV_MvdMulticast(), SV_MvdRunClients(), SV_MvdShutdown(), SV_MvdStartSound(), SV_MvdStop_f(), SV_MvdStuff_f(), SV_MvdUnicast(), and update_player_name().

◆ sv_mvd_allow_stufftext

cvar_t* sv_mvd_allow_stufftext
static

Definition at line 106 of file mvd.c.

Referenced by dummy_add_message(), parse_hello(), and SV_MvdRegister().

◆ sv_mvd_autorecord

cvar_t* sv_mvd_autorecord
static

Definition at line 102 of file mvd.c.

Referenced by dummy_record_f(), dummy_stop_f(), SV_MvdMapChanged(), and SV_MvdRegister().

◆ sv_mvd_begincmd

cvar_t* sv_mvd_begincmd
static

Definition at line 100 of file mvd.c.

Referenced by dummy_spawn(), and SV_MvdRegister().

◆ sv_mvd_bufsize

cvar_t* sv_mvd_bufsize
static

Definition at line 92 of file mvd.c.

Referenced by parse_hello(), and SV_MvdRegister().

◆ sv_mvd_capture_flags

cvar_t* sv_mvd_capture_flags
static

Definition at line 103 of file mvd.c.

Referenced by player_is_active(), and SV_MvdRegister().

◆ sv_mvd_disconnect_time

cvar_t* sv_mvd_disconnect_time
static

Definition at line 104 of file mvd.c.

Referenced by check_clients_activity(), and SV_MvdRegister().

◆ sv_mvd_enable

cvar_t* sv_mvd_enable
static

Definition at line 90 of file mvd.c.

Referenced by SV_MvdInit(), and SV_MvdRegister().

◆ sv_mvd_maxclients

cvar_t* sv_mvd_maxclients
static

Definition at line 91 of file mvd.c.

Referenced by find_slot(), SV_MvdInit(), and SV_MvdRegister().

◆ sv_mvd_maxmaps

cvar_t* sv_mvd_maxmaps
static

Definition at line 99 of file mvd.c.

Referenced by SV_MvdMapChanged(), and SV_MvdRegister().

◆ sv_mvd_maxsize

cvar_t* sv_mvd_maxsize
static

Definition at line 97 of file mvd.c.

Referenced by rec_frame(), and SV_MvdRegister().

◆ sv_mvd_maxtime

cvar_t* sv_mvd_maxtime
static

Definition at line 98 of file mvd.c.

Referenced by rec_frame(), and SV_MvdRegister().

◆ sv_mvd_noblend

cvar_t* sv_mvd_noblend
static

Definition at line 94 of file mvd.c.

Referenced by emit_frame(), emit_gamestate(), and SV_MvdRegister().

◆ sv_mvd_nogun

cvar_t* sv_mvd_nogun
static

Definition at line 95 of file mvd.c.

Referenced by emit_frame(), emit_gamestate(), and SV_MvdRegister().

◆ sv_mvd_nomsgs

cvar_t* sv_mvd_nomsgs
static

Definition at line 96 of file mvd.c.

Referenced by emit_gamestate(), filter_unicast_data(), and SV_MvdRegister().

◆ sv_mvd_password

cvar_t* sv_mvd_password
static

Definition at line 93 of file mvd.c.

Referenced by auth_client(), and SV_MvdRegister().

◆ sv_mvd_scorecmd

cvar_t* sv_mvd_scorecmd
static

Definition at line 101 of file mvd.c.

Referenced by dummy_run(), and SV_MvdRegister().

◆ sv_mvd_spawn_dummy

cvar_t* sv_mvd_spawn_dummy
static

Definition at line 107 of file mvd.c.

Referenced by dummy_create(), and SV_MvdRegister().

◆ sv_mvd_suspend_time

cvar_t* sv_mvd_suspend_time
static

Definition at line 105 of file mvd.c.

Referenced by check_players_activity(), and SV_MvdRegister().

mvd_server_t::players_active
unsigned players_active
Definition: mvd.c:60
parse_hello
static void parse_hello(gtv_client_t *client)
Definition: mvd.c:1455
dummy_add_message
static void dummy_add_message(client_t *client, byte *data, size_t length, qboolean reliable)
Definition: mvd.c:272
Z_ReservedAlloc
void * Z_ReservedAlloc(size_t size)
Definition: zone.c:349
gtv_client_t::entry
list_t entry
Definition: mvd.c:33
sv_mvd_disconnect_time
static cvar_t * sv_mvd_disconnect_time
Definition: mvd.c:104
SV_DelMatch_f
void SV_DelMatch_f(list_t *list)
Definition: commands.c:1119
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
mvd_server_t::numlevels
int numlevels
Definition: mvd.c:74
mvd_server_t::numframes
int numframes
Definition: mvd.c:75
rec_write
static void rec_write(void)
Definition: mvd.c:2153
cs_spawned
@ cs_spawned
Definition: server.h:192
mvd_server_t::players
player_packed_t * players
Definition: mvd.c:69
msg_read
sizebuf_t msg_read
Definition: msg.c:37
parse_stringcmd
static void parse_stringcmd(gtv_client_t *client)
Definition: mvd.c:1608
mvd_disable
static void mvd_disable(void)
Definition: mvd.c:940
mvd_server_t::message
sizebuf_t message
Definition: mvd.c:63
svs
server_static_t svs
Definition: init.c:21
NET_AdrToString
char * NET_AdrToString(const netadr_t *a)
Definition: net.c:257
cmd_optarg
char * cmd_optarg
Definition: cmd.c:848
sv_iplimit
cvar_t * sv_iplimit
Definition: main.c:87
players_active
static qboolean players_active(void)
Definition: mvd.c:868
mvd_drop
static void mvd_drop(gtv_serverop_t op)
Definition: mvd.c:1926
gtv_client_t::msglen
unsigned msglen
Definition: mvd.c:40
remove_client
static void remove_client(gtv_client_t *client)
Definition: mvd.c:1302
gtv_client_t::version
char version[MAX_QPATH]
Definition: mvd.c:51
client_s::protocol
int protocol
Definition: server.h:324
gtv_client_t::flags
unsigned flags
Definition: mvd.c:43
dump_clients
static void dump_clients(void)
Definition: mvd.c:1857
dummy_spawn
static void dummy_spawn(void)
Definition: mvd.c:291
FIFO_ReadMessage
qboolean FIFO_ReadMessage(fifo_t *fifo, size_t msglen)
Definition: fifo.c:89
SV_AddGtvHost_f
static void SV_AddGtvHost_f(void)
Definition: mvd.c:2326
dummy_run
static void dummy_run(void)
Definition: mvd.c:418
password
cvar_t * password
Definition: g_main.c:39
gtv_client_t::state
clstate_t state
Definition: mvd.c:35
gtv_client_t::active
list_t active
Definition: mvd.c:34
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
dummy_exec_string
static void dummy_exec_string(cmdbuf_t *buf, const char *line)
Definition: mvd.c:229
client_s::state
clstate_t state
Definition: server.h:260
client_s::number
int number
Definition: server.h:262
sv_ghostime
cvar_t * sv_ghostime
Definition: main.c:45
sv_mvd_begincmd
static cvar_t * sv_mvd_begincmd
Definition: mvd.c:100
MSG_ReadWord
int MSG_ReadWord(void)
Definition: msg.c:1503
sv_mvd_maxtime
static cvar_t * sv_mvd_maxtime
Definition: mvd.c:98
client_s::slot
int slot
Definition: server.h:347
MVD_USERINFO1
#define MVD_USERINFO1
Definition: mvd.c:336
emit_gamestate
static void emit_gamestate(void)
Definition: mvd.c:595
SV_FRAMESYNC
#define SV_FRAMESYNC
Definition: server.h:141
NET_UpdateStream
void NET_UpdateStream(netstream_t *s)
Definition: net.c:1628
SZ_WriteByte
void SZ_WriteByte(sizebuf_t *sb, int c)
Definition: sizebuf.c:82
rec_start
static void rec_start(qhandle_t demofile)
Definition: mvd.c:2206
sv_mvd_password
static cvar_t * sv_mvd_password
Definition: mvd.c:93
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
Cmd_Args
char * Cmd_Args(void)
Definition: cmd.c:933
NET_CloseStream
void NET_CloseStream(netstream_t *s)
Definition: net.c:1371
SV_ListMatches_f
void SV_ListMatches_f(list_t *list)
Definition: commands.c:1176
FOR_EACH_ACTIVE_GTV
#define FOR_EACH_ACTIVE_GTV(client)
Definition: mvd.c:29
SV_DelGtvBan_f
static void SV_DelGtvBan_f(void)
Definition: mvd.c:2343
Cbuf_InsertText
void Cbuf_InsertText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:128
Cmd_TokenizeString
void Cmd_TokenizeString(const char *text, qboolean macroExpand)
Definition: cmd.c:1399
mvd_server_t::datagram
sizebuf_t datagram
Definition: mvd.c:66
Cmd_Shift
void Cmd_Shift(void)
Definition: cmd.c:1034
sv_timeout
cvar_t * sv_timeout
Definition: main.c:43
sv_mvd_allow_stufftext
static cvar_t * sv_mvd_allow_stufftext
Definition: mvd.c:106
sv_client
client_t * sv_client
Definition: main.c:32
dummy_record_f
static void dummy_record_f(void)
Definition: mvd.c:166
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
dummy_command
static void dummy_command(void)
Definition: mvd.c:150
mvd_server_t::clients_active
unsigned clients_active
Definition: mvd.c:59
sv_mvd_suspend_time
static cvar_t * sv_mvd_suspend_time
Definition: mvd.c:105
mvd_server_t::entities
entity_packed_t * entities
Definition: mvd.c:70
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
svc_stufftext
#define svc_stufftext
Definition: g_local.h:41
SZ_Init
void SZ_Init(sizebuf_t *buf, void *data, size_t size)
Definition: sizebuf.c:31
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
net_from
netadr_t net_from
Definition: net.c:90
mvd_server_t::active
qboolean active
Definition: mvd.c:56
SV_UserinfoChanged
void SV_UserinfoChanged(client_t *cl)
Definition: main.c:1927
MVD_USERINFO2
#define MVD_USERINFO2
Definition: mvd.c:339
mvd_error
static void mvd_error(const char *reason)
Definition: mvd.c:1961
write_message
static void write_message(gtv_client_t *client, gtv_serverop_t op)
Definition: mvd.c:1427
SV_Malloc
#define SV_Malloc(size)
Definition: server.h:54
sv_reserved_slots
cvar_t * sv_reserved_slots
Definition: main.c:59
NET_Accept
neterr_t NET_Accept(netstream_t *s)
Definition: net.c:1525
gtv_client_t::maxbuf
unsigned maxbuf
Definition: mvd.c:44
ES_INUSE
#define ES_INUSE(s)
Definition: server.h:718
parse_stream_start
static void parse_stream_start(gtv_client_t *client)
Definition: mvd.c:1547
mvd_server_t::recording
qhandle_t recording
Definition: mvd.c:73
SV_MvdStuff_f
static void SV_MvdStuff_f(void)
Definition: mvd.c:2316
FOR_EACH_GTV
#define FOR_EACH_GTV(client)
Definition: mvd.c:26
MSG_PackEntity
void MSG_PackEntity(entity_packed_t *out, const entity_state_t *in, qboolean short_angles)
Definition: msg.c:468
NET_Listen
neterr_t NET_Listen(qboolean arg)
Definition: net.c:1466
dummy_cmds
static const ucmd_t dummy_cmds[]
Definition: mvd.c:215
resume_streams
static void resume_streams(void)
Definition: mvd.c:836
dummy_buffer
static cmdbuf_t dummy_buffer
Definition: mvd.c:137
MSG_PackPlayer
void MSG_PackPlayer(player_packed_t *out, const player_state_t *in)
Definition: msg.c:763
c_svmvd
static const cmdreg_t c_svmvd[]
Definition: mvd.c:2352
NUM_FOR_EDICT
#define NUM_FOR_EDICT(e)
Definition: server.h:174
sv
server_t sv
Definition: init.c:22
mvd
static mvd_server_t mvd
Definition: mvd.c:81
Cmd_ParseOptions
int Cmd_ParseOptions(const cmd_option_t *opt)
Definition: cmd.c:1057
msg_write
sizebuf_t msg_write
Definition: msg.c:34
NET_ErrorString
const char * NET_ErrorString(void)
Definition: net.c:659
suspend_streams
static void suspend_streams(void)
Definition: mvd.c:819
client_s::entry
list_t entry
Definition: server.h:257
gtv_client_t::data
byte * data
Definition: mvd.c:48
Cbuf_AddText
void Cbuf_AddText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:95
mvd_enable
static qboolean mvd_enable(void)
Definition: mvd.c:913
Info_ValueForKey
char * Info_ValueForKey(const char *s, const char *key)
Definition: shared.c:945
dump_versions
static void dump_versions(void)
Definition: mvd.c:1895
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
sv_zombietime
cvar_t * sv_zombietime
Definition: main.c:44
server_static_s::client_pool
client_t * client_pool
Definition: server.h:456
find_slot
static gtv_client_t * find_slot(void)
Definition: mvd.c:1713
CM_WritePortalBits
int CM_WritePortalBits(cm_t *cm, byte *buffer)
Definition: cmodel.c:955
rec_stop
static void rec_stop(void)
Definition: mvd.c:2175
Cmd_Register
void Cmd_Register(const cmdreg_t *reg)
Definition: cmd.c:1572
MSG_ReadLong
int MSG_ReadLong(void)
Definition: msg.c:1517
sv_mvd_maxclients
static cvar_t * sv_mvd_maxclients
Definition: mvd.c:91
MSG_WriteDeltaEntity
void MSG_WriteDeltaEntity(const entity_packed_t *from, const entity_packed_t *to, msgEsFlags_t flags)
Definition: msg.c:505
cs_free
@ cs_free
Definition: server.h:186
sv_mvd_noblend
static cvar_t * sv_mvd_noblend
Definition: mvd.c:94
dummy_stop_f
static void dummy_stop_f(void)
Definition: mvd.c:200
cs_zombie
@ cs_zombie
Definition: server.h:187
rec_frame
static void rec_frame(size_t total)
Definition: mvd.c:961
fs_game
cvar_t * fs_game
Definition: files.c:202
gtv_client_t
Definition: mvd.c:32
copy_entity_state
static void copy_entity_state(entity_packed_t *dst, const entity_packed_t *src, int flags)
Definition: mvd.c:686
gtv_client_t::lastmessage
unsigned lastmessage
Definition: mvd.c:41
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
sv_mvd_bufsize
static cvar_t * sv_mvd_bufsize
Definition: mvd.c:92
check_clients_activity
static void check_clients_activity(void)
Definition: mvd.c:885
sv_mvd_nogun
static cvar_t * sv_mvd_nogun
Definition: mvd.c:95
Cmd_Alias_f
void Cmd_Alias_f(void)
Definition: cmd.c:307
MSG_WriteShort
void MSG_WriteShort(int c)
Definition: msg.c:125
ge
game_export_t * ge
Definition: game.c:22
Cmd_AliasCommand
char * Cmd_AliasCommand(const char *name)
Definition: cmd.c:251
write_stream
static void write_stream(gtv_client_t *client, void *data, size_t len)
Definition: mvd.c:1379
SV_DropClient
void SV_DropClient(client_t *client, const char *reason)
Definition: main.c:212
sv_mvd_maxmaps
static cvar_t * sv_mvd_maxmaps
Definition: mvd.c:99
sv_mvd_scorecmd
static cvar_t * sv_mvd_scorecmd
Definition: mvd.c:101
o_record
static const cmd_option_t o_record[]
Definition: demo.c:299
dummy_wait_f
static void dummy_wait_f(void)
Definition: mvd.c:140
drop_client
static void drop_client(gtv_client_t *client, const char *error)
Definition: mvd.c:1353
parse_message
static qboolean parse_message(gtv_client_t *client)
Definition: mvd.c:1632
parse_ping
static void parse_ping(gtv_client_t *client)
Definition: mvd.c:1533
check_players_activity
static void check_players_activity(void)
Definition: mvd.c:897
Z_TagReserve
void Z_TagReserve(size_t size, memtag_t tag)
Definition: zone.c:342
gtv_client_t::stream
netstream_t stream
Definition: mvd.c:36
FS_Write
ssize_t FS_Write(const void *buf, size_t len, qhandle_t f)
Definition: files.c:1643
SV_DelGtvHost_f
static void SV_DelGtvHost_f(void)
Definition: mvd.c:2330
mvd_server_t::dummy
client_t * dummy
Definition: mvd.c:57
sv_mvd_capture_flags
static cvar_t * sv_mvd_capture_flags
Definition: mvd.c:103
SV_ListGtvHosts_f
static void SV_ListGtvHosts_f(void)
Definition: mvd.c:2334
mvd_server_t::layout_time
unsigned layout_time
Definition: mvd.c:58
server_t::cm
cm_t cm
Definition: server.h:161
MSG_WriteString
void MSG_WriteString(const char *string)
Definition: msg.c:160
c
statCounters_t c
Definition: main.c:30
MSG_WriteLong
void MSG_WriteLong(int c)
Definition: msg.c:144
Cvar_Command
void Cvar_Command(cvar_t *v)
Definition: cvar.c:672
cs_assigned
@ cs_assigned
Definition: server.h:189
accept_client
static void accept_client(netstream_t *stream)
Definition: mvd.c:1728
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
g_features
cvar_t * g_features
Definition: main.c:99
Cvar_Set_f
void Cvar_Set_f(void)
Definition: cvar.c:717
MSG_ReadString
size_t MSG_ReadString(char *dest, size_t size)
Definition: msg.c:1531
dummy_buffer_text
static char dummy_buffer_text[MAX_STRING_CHARS]
Definition: mvd.c:138
sv_mvd_autorecord
static cvar_t * sv_mvd_autorecord
Definition: mvd.c:102
server_static_s::realtime
unsigned realtime
Definition: server.h:454
level
level_locals_t level
Definition: g_main.c:22
client_s::AddMessage
void(* AddMessage)(struct client_s *, byte *, size_t, qboolean)
Definition: server.h:352
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
cs_primed
@ cs_primed
Definition: server.h:191
Cmd_PrintHint
void Cmd_PrintHint(void)
Definition: cmd.c:1178
server_t::state
server_state_t state
Definition: server.h:146
gtv_client_t::buffer
byte buffer[MAX_GTC_MSGLEN+4]
Definition: mvd.c:47
gtv_client_t::bufcount
unsigned bufcount
Definition: mvd.c:45
sv_player
edict_t * sv_player
Definition: main.c:33
client_s::netchan
netchan_t * netchan
Definition: server.h:357
client_s
Definition: server.h:256
SV_Mallocz
#define SV_Mallocz(size)
Definition: server.h:55
svc_layout
#define svc_layout
Definition: g_local.h:39
player_is_active
static qboolean player_is_active(const edict_t *ent)
Definition: mvd.c:479
Cvar_FindVar
cvar_t * Cvar_FindVar(const char *var_name)
Definition: cvar.c:45
SV_MatchAddress
addrmatch_t * SV_MatchAddress(list_t *list, netadr_t *addr)
Definition: main.c:370
NET_RunStream
neterr_t NET_RunStream(netstream_t *s)
Definition: net.c:1647
dummy_forward_f
static void dummy_forward_f(void)
Definition: mvd.c:159
emit_frame
static void emit_frame(void)
Definition: mvd.c:711
FS_FCloseFile
void FS_FCloseFile(qhandle_t f)
Definition: files.c:759
rec_allowed
static qboolean rec_allowed(void)
Definition: mvd.c:2191
MSG_ReadByte
int MSG_ReadByte(void)
Definition: msg.c:1475
EDICT_NUM
#define EDICT_NUM(n)
Definition: server.h:173
NET_Sleep
int NET_Sleep(int msec)
Definition: net.c:712
server_t::spawncount
int spawncount
Definition: server.h:147
sv_mvd_enable
static cvar_t * sv_mvd_enable
Definition: mvd.c:90
parse_stream_stop
static void parse_stream_stop(gtv_client_t *client)
Definition: mvd.c:1590
server_t::configstrings
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH]
Definition: server.h:164
FIFO_Write
size_t FIFO_Write(fifo_t *fifo, const void *buffer, size_t len)
Definition: fifo.c:50
filter_unicast_data
static qboolean filter_unicast_data(edict_t *ent)
Definition: mvd.c:1149
SV_RemoveClient
void SV_RemoveClient(client_t *client)
Definition: main.c:107
build_gamestate
static void build_gamestate(void)
Definition: mvd.c:560
auth_client
static qboolean auth_client(gtv_client_t *client, const char *password)
Definition: mvd.c:1440
mvd_server_t::enabled
qboolean enabled
Definition: mvd.c:55
SV_AddGtvBan_f
static void SV_AddGtvBan_f(void)
Definition: mvd.c:2339
dummy_find_slot
static client_t * dummy_find_slot(void)
Definition: mvd.c:311
sv_mvd_spawn_dummy
static cvar_t * sv_mvd_spawn_dummy
Definition: mvd.c:107
client_s::userinfo
char userinfo[MAX_INFO_STRING]
Definition: server.h:275
SV_AddMatch_f
void SV_AddMatch_f(list_t *list)
Definition: commands.c:1082
dummy_create
static int dummy_create(void)
Definition: mvd.c:342
cs_connected
@ cs_connected
Definition: server.h:190
entity_is_active
static qboolean entity_is_active(const edict_t *ent)
Definition: mvd.c:546
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
mvd_server_t::clients
gtv_client_t * clients
Definition: mvd.c:78
sv_mvd_maxsize
static cvar_t * sv_mvd_maxsize
Definition: mvd.c:97
gtv_client_t::name
char name[MAX_CLIENT_NAME]
Definition: mvd.c:50
sv_mvd_nomsgs
static cvar_t * sv_mvd_nomsgs
Definition: mvd.c:96
SV_ListGtvBans_f
static void SV_ListGtvBans_f(void)
Definition: mvd.c:2347
MSG_ReadShort
int MSG_ReadShort(void)
Definition: msg.c:1489
client_s::edict
edict_t * edict
Definition: server.h:261
sv_maxclients
cvar_t * sv_maxclients
Definition: main.c:58
Cmd_RawArgs
char * Cmd_RawArgs(void)
Definition: cmd.c:951