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

Go to the source code of this file.

Macros

#define SHOWNET(...)
 
#define RELINK_MASK   (U_MODEL|U_ORIGIN1|U_ORIGIN2|U_ORIGIN3|U_SOLID)
 

Functions

void MVD_ParseEntityString (mvd_t *mvd, const char *data)
 
static void MVD_ParseMulticast (mvd_t *mvd, mvd_ops_t op, int extrabits)
 
static void MVD_UnicastSend (mvd_t *mvd, qboolean reliable, byte *data, size_t length, mvd_player_t *player)
 
static void MVD_UnicastLayout (mvd_t *mvd, mvd_player_t *player)
 
static void MVD_UnicastString (mvd_t *mvd, qboolean reliable, mvd_player_t *player)
 
static void MVD_UnicastPrint (mvd_t *mvd, qboolean reliable, mvd_player_t *player)
 
static void MVD_UnicastStuff (mvd_t *mvd, qboolean reliable, mvd_player_t *player)
 
static void MVD_ParseUnicast (mvd_t *mvd, mvd_ops_t op, int extrabits)
 
static void MVD_ParseSound (mvd_t *mvd, int extrabits)
 
static void MVD_ParseConfigstring (mvd_t *mvd)
 
static void MVD_ParsePrint (mvd_t *mvd)
 
static void MVD_PlayerToEntityStates (mvd_t *mvd)
 
static void MVD_ParsePacketEntities (mvd_t *mvd)
 
static void MVD_ParsePacketPlayers (mvd_t *mvd)
 
static void MVD_ParseFrame (mvd_t *mvd)
 
void MVD_ClearState (mvd_t *mvd, qboolean full)
 
static void MVD_ChangeLevel (mvd_t *mvd)
 
static void MVD_ParseServerData (mvd_t *mvd, int extrabits)
 
qboolean MVD_ParseMessage (mvd_t *mvd)
 

Variables

static qboolean match_ended_hack
 

Macro Definition Documentation

◆ RELINK_MASK

#define RELINK_MASK   (U_MODEL|U_ORIGIN1|U_ORIGIN2|U_ORIGIN3|U_SOLID)

Definition at line 697 of file parse.c.

◆ SHOWNET

#define SHOWNET (   ...)

Definition at line 61 of file parse.c.

Function Documentation

◆ MVD_ChangeLevel()

static void MVD_ChangeLevel ( mvd_t mvd)
static

Definition at line 901 of file parse.c.

902 {
903  mvd_client_t *client;
904 
905  if (sv.state != ss_broadcast) {
906  // the game is just starting
908  MVD_Spawn();
909  return;
910  }
911 
912  // cause all UDP clients to reconnect
914  MSG_WriteString(va("changing map=%s; reconnect\n", mvd->mapname));
915 
916  FOR_EACH_MVDCL(client, mvd) {
917  if (client->target != mvd->dummy) {
918  // make them switch to previous target instead of MVD dummy
919  client->oldtarget = client->target;
920  }
921  client->target = NULL;
922  SV_ClientReset(client->cl);
923  client->cl->spawncount = mvd->servercount;
925  }
926 
928 
929  mvd->intermission = qfalse;
930 
931  mvd_dirty = qtrue;
932 
934 }

Referenced by MVD_ParseServerData().

◆ MVD_ClearState()

void MVD_ClearState ( mvd_t mvd,
qboolean  full 
)

Definition at line 856 of file parse.c.

857 {
858  mvd_player_t *player;
859  mvd_snap_t *snap, *next;
860  int i;
861 
862  // clear all entities, don't trust num_edicts as it is possible
863  // to miscount removed but seen entities
864  memset(mvd->edicts, 0, sizeof(mvd->edicts));
865  mvd->pool.num_edicts = 0;
866 
867  // clear all players
868  for (i = 0; i < mvd->maxclients; i++) {
869  player = &mvd->players[i];
870  MVD_FreePlayer(player);
871  memset(player, 0, sizeof(*player));
872  }
873 
874  mvd->numplayers = 0;
875 
876  if (!full)
877  return;
878 
879  // free all snapshots
880  LIST_FOR_EACH_SAFE(mvd_snap_t, snap, next, &mvd->snapshots, entry) {
881  Z_Free(snap);
882  }
883 
884  List_Init(&mvd->snapshots);
885 
886  // free current map
887  CM_FreeMap(&mvd->cm);
888 
889  if (mvd->intermission) {
890  // save oldscores
891  //strcpy(mvd->oldscores, mvd->layout);
892  }
893 
894  memset(mvd->configstrings, 0, sizeof(mvd->configstrings));
895  mvd->layout[0] = 0;
896 
897  mvd->framenum = 0;
898  // intermission flag will be cleared in MVD_ChangeLevel
899 }

Referenced by MVD_ParseServerData(), and MVD_Seek_f().

◆ MVD_ParseConfigstring()

static void MVD_ParseConfigstring ( mvd_t mvd)
static

Definition at line 619 of file parse.c.

620 {
621  int index;
622  size_t len, maxlen;
623  char *s;
624 
625  index = MSG_ReadShort();
626  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
627  MVD_Destroyf(mvd, "%s: bad index: %d", __func__, index);
628  }
629 
630  s = mvd->configstrings[index];
631  maxlen = CS_SIZE(index);
632  len = MSG_ReadString(s, maxlen);
633  if (len >= maxlen) {
634  MVD_Destroyf(mvd, "%s: index %d overflowed", __func__, index);
635  }
636 
637  if (mvd->demoseeking) {
638  Q_SetBit(mvd->dcs, index);
639  return;
640  }
641 
642  MVD_UpdateConfigstring(mvd, index);
643 }

Referenced by MVD_ParseMessage().

◆ MVD_ParseEntityString()

void MVD_ParseEntityString ( mvd_t mvd,
const char *  data 
)

Definition at line 64 of file parse.c.

65 {
66  const char *p;
67  char key[MAX_STRING_CHARS];
68  char value[MAX_STRING_CHARS];
69  char classname[MAX_QPATH];
70  vec3_t origin;
71  vec3_t angles;
72 
73  while (data) {
74  p = COM_Parse(&data);
75  if (!p[0]) {
76  break;
77  }
78  if (p[0] != '{') {
79  Com_Error(ERR_DROP, "expected '{', found '%s'", p);
80  }
81 
82  classname[0] = 0;
83  VectorClear(origin);
84  VectorClear(angles);
85  while (1) {
86  p = COM_Parse(&data);
87  if (p[0] == '}') {
88  break;
89  }
90  if (p[0] == '{') {
91  Com_Error(ERR_DROP, "expected key, found '{'");
92  }
93 
94  Q_strlcpy(key, p, sizeof(key));
95 
96  p = COM_Parse(&data);
97  if (!data) {
98  Com_Error(ERR_DROP, "expected key/value pair, found EOF");
99  }
100  if (p[0] == '}' || p[0] == '{') {
101  Com_Error(ERR_DROP, "expected value, found '%s'", p);
102  }
103 
104  if (!strcmp(key, "classname")) {
105  Q_strlcpy(classname, p, sizeof(classname));
106  continue;
107  }
108 
109  Q_strlcpy(value, p, sizeof(value));
110 
111  p = value;
112  if (!strcmp(key, "origin")) {
113  origin[0] = atof(COM_Parse(&p));
114  origin[1] = atof(COM_Parse(&p));
115  origin[2] = atof(COM_Parse(&p));
116  } else if (!strncmp(key, "angle", 5)) {
117  if (key[5] == 0) {
118  angles[0] = 0;
119  angles[1] = atof(COM_Parse(&p));
120  angles[2] = 0;
121  } else if (key[5] == 's' && key[6] == 0) {
122  angles[0] = atof(COM_Parse(&p));
123  angles[1] = atof(COM_Parse(&p));
124  angles[2] = atof(COM_Parse(&p));
125  }
126  }
127  }
128 
129  if (!classname[0]) {
130  Com_Error(ERR_DROP, "entity with no classname");
131  }
132 
133  if (strncmp(classname, "info_player_", 12)) {
134  continue;
135  }
136 
137  if (!strcmp(classname + 12, "intermission")) {
138  VectorCopy(origin, mvd->spawnOrigin);
139  VectorCopy(angles, mvd->spawnAngles);
140  break;
141  }
142 
143  if (!strcmp(classname + 12, "start") ||
144  !strcmp(classname + 12, "deathmatch")) {
145  VectorCopy(origin, mvd->spawnOrigin);
146  VectorCopy(angles, mvd->spawnAngles);
147  }
148 
149  }
150 }

Referenced by MVD_GameInit(), and MVD_ParseServerData().

◆ MVD_ParseFrame()

static void MVD_ParseFrame ( mvd_t mvd)
static

Definition at line 817 of file parse.c.

818 {
819  byte *data;
820  int length;
821 
822  // read portalbits
823  length = MSG_ReadByte();
824  if (length) {
825  if (length < 0 || msg_read.readcount + length > msg_read.cursize) {
826  MVD_Destroyf(mvd, "%s: read past end of message", __func__);
827  }
828  if (length > MAX_MAP_PORTAL_BYTES) {
829  MVD_Destroyf(mvd, "%s: bad portalbits length: %d", __func__, length);
830  }
831  data = msg_read.data + msg_read.readcount;
832  msg_read.readcount += length;
833  } else {
834  data = NULL;
835  }
836 
837  if (!mvd->demoseeking)
838  CM_SetPortalStates(&mvd->cm, data, length);
839 
840  SHOWNET(1, "%3"PRIz":playerinfo\n", msg_read.readcount - 1);
842  SHOWNET(1, "%3"PRIz":packetentities\n", msg_read.readcount - 1);
844  SHOWNET(1, "%3"PRIz":frame:%u\n", msg_read.readcount - 1, mvd->framenum);
846 
847  // update clients now so that effects datagram that
848  // follows can reference current view positions
849  if (mvd->state && mvd->framenum && !mvd->demoseeking) {
851  }
852 
853  mvd->framenum++;
854 }

Referenced by MVD_ParseMessage(), and MVD_ParseServerData().

◆ MVD_ParseMessage()

qboolean MVD_ParseMessage ( mvd_t mvd)

Definition at line 1098 of file parse.c.

1099 {
1100  int cmd, extrabits;
1101  qboolean ret = qfalse;
1102 
1103 #ifdef _DEBUG
1104  if (mvd_shownet->integer == 1) {
1105  Com_Printf("%"PRIz" ", msg_read.cursize);
1106  } else if (mvd_shownet->integer > 1) {
1107  Com_Printf("------------------\n");
1108  }
1109 #endif
1110 
1111 //
1112 // parse the message
1113 //
1114  match_ended_hack = qfalse;
1115  while (1) {
1116  if (msg_read.readcount > msg_read.cursize) {
1117  MVD_Destroyf(mvd, "Read past end of message");
1118  }
1119  if (msg_read.readcount == msg_read.cursize) {
1120  SHOWNET(1, "%3"PRIz":END OF MESSAGE\n", msg_read.readcount - 1);
1121  break;
1122  }
1123 
1124  cmd = MSG_ReadByte();
1125  extrabits = cmd >> SVCMD_BITS;
1126  cmd &= SVCMD_MASK;
1127 
1128 #ifdef _DEBUG
1129  if (mvd_shownet->integer > 1) {
1130  MVD_ShowSVC(cmd);
1131  }
1132 #endif
1133 
1134  switch (cmd) {
1135  case mvd_serverdata:
1136  MVD_ParseServerData(mvd, extrabits);
1137  ret |= qtrue;
1138  break;
1139  case mvd_multicast_all:
1140  case mvd_multicast_pvs:
1141  case mvd_multicast_phs:
1142  case mvd_multicast_all_r:
1143  case mvd_multicast_pvs_r:
1144  case mvd_multicast_phs_r:
1145  MVD_ParseMulticast(mvd, cmd, extrabits);
1146  break;
1147  case mvd_unicast:
1148  case mvd_unicast_r:
1149  MVD_ParseUnicast(mvd, cmd, extrabits);
1150  break;
1151  case mvd_configstring:
1153  break;
1154  case mvd_frame:
1156  break;
1157  case mvd_sound:
1158  MVD_ParseSound(mvd, extrabits);
1159  break;
1160  case mvd_print:
1162  break;
1163  case mvd_nop:
1164  break;
1165  default:
1166  MVD_Destroyf(mvd, "Illegible command at %"PRIz": %d",
1167  msg_read.readcount - 1, cmd);
1168  }
1169  }
1170 
1171  return ret;
1172 }

Referenced by demo_play_next(), demo_read_frame(), gtv_read_frame(), MVD_Seek_f(), and parse_stream_data().

◆ MVD_ParseMulticast()

static void MVD_ParseMulticast ( mvd_t mvd,
mvd_ops_t  op,
int  extrabits 
)
static

Definition at line 152 of file parse.c.

153 {
154  mvd_client_t *client;
155  client_t *cl;
156  byte mask[VIS_MAX_BYTES];
157  mleaf_t *leaf1, *leaf2;
158  vec3_t org;
159  qboolean reliable = qfalse;
160  player_state_t *ps;
161  byte *data;
162  int length, leafnum;
163 
164  length = MSG_ReadByte();
165  length |= extrabits << 8;
166 
167  switch (op) {
168  case mvd_multicast_all_r:
169  reliable = qtrue;
170  // intentional fallthrough
171  case mvd_multicast_all:
172  leaf1 = NULL;
173  break;
174  case mvd_multicast_phs_r:
175  reliable = qtrue;
176  // intentional fallthrough
177  case mvd_multicast_phs:
178  leafnum = MSG_ReadWord();
179  if (mvd->demoseeking) {
180  leaf1 = NULL;
181  break;
182  }
183  leaf1 = CM_LeafNum(&mvd->cm, leafnum);
184  BSP_ClusterVis(mvd->cm.cache, mask, leaf1->cluster, DVIS_PHS);
185  break;
186  case mvd_multicast_pvs_r:
187  reliable = qtrue;
188  // intentional fallthrough
189  case mvd_multicast_pvs:
190  leafnum = MSG_ReadWord();
191  if (mvd->demoseeking) {
192  leaf1 = NULL;
193  break;
194  }
195  leaf1 = CM_LeafNum(&mvd->cm, leafnum);
196  BSP_ClusterVis(mvd->cm.cache, mask, leaf1->cluster, DVIS_PVS);
197  break;
198  default:
199  MVD_Destroyf(mvd, "bad op");
200  }
201 
202  // skip data payload
203  data = msg_read.data + msg_read.readcount;
204  msg_read.readcount += length;
205  if (msg_read.readcount > msg_read.cursize) {
206  MVD_Destroyf(mvd, "read past end of message");
207  }
208 
209  if (mvd->demoseeking)
210  return;
211 
212  // send the data to all relevent clients
213  FOR_EACH_MVDCL(client, mvd) {
214  cl = client->cl;
215  if (cl->state < cs_primed) {
216  continue;
217  }
218 
219  // do not send unreliables to connecting clients
220  if (!reliable && (cl->state != cs_spawned || cl->download || cl->nodata)) {
221  continue;
222  }
223 
224  if (leaf1) {
225  // find the client's PVS
226  ps = &client->ps;
227 #if 0
228  VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin, org);
229 #else
230  // FIXME: for some strange reason, game code assumes the server
231  // uses entity origin for PVS/PHS culling, not the view origin
232  VectorScale(ps->pmove.origin, 0.125f, org);
233 #endif
234  leaf2 = CM_PointLeaf(&mvd->cm, org);
235  if (!CM_AreasConnected(&mvd->cm, leaf1->area, leaf2->area))
236  continue;
237  if (leaf2->cluster == -1)
238  continue;
239  if (!Q_IsBitSet(mask, leaf2->cluster))
240  continue;
241  }
242 
243  cl->AddMessage(cl, data, length, reliable);
244  }
245 }

Referenced by MVD_ParseMessage().

◆ MVD_ParsePacketEntities()

static void MVD_ParsePacketEntities ( mvd_t mvd)
static

Definition at line 704 of file parse.c.

705 {
706  int number;
707  int bits;
708  edict_t *ent;
709 
710  while (1) {
711  if (msg_read.readcount > msg_read.cursize) {
712  MVD_Destroyf(mvd, "%s: read past end of message", __func__);
713  }
714 
715  number = MSG_ParseEntityBits(&bits);
716  if (number < 0 || number >= MAX_EDICTS) {
717  MVD_Destroyf(mvd, "%s: bad number: %d", __func__, number);
718  }
719 
720  if (!number) {
721  break;
722  }
723 
724  ent = &mvd->edicts[number];
725 
726 #ifdef _DEBUG
727  if (mvd_shownet->integer > 2) {
728  Com_Printf(" %s: %d ", ent->inuse ?
729  "delta" : "baseline", number);
730  MSG_ShowDeltaEntityBits(bits);
731  Com_Printf("\n");
732  }
733 #endif
734 
735  MSG_ParseDeltaEntity(&ent->s, &ent->s, number, bits, 0);
736 
737  // lazily relink even if removed
738  if ((bits & RELINK_MASK) && !mvd->demoseeking) {
739  MVD_LinkEdict(mvd, ent);
740  }
741 
742  // mark this entity as seen even if removed
743  ent->svflags |= SVF_MONSTER;
744 
745  // shuffle current origin to old if removed
746  if (bits & U_REMOVE) {
747  SHOWNET(2, " remove: %d\n", number);
748  if (!(ent->s.renderfx & RF_BEAM)) {
749  VectorCopy(ent->s.origin, ent->s.old_origin);
750  }
751  ent->inuse = qfalse;
752  continue;
753  }
754 
755  ent->inuse = qtrue;
756  if (number >= mvd->pool.num_edicts) {
757  mvd->pool.num_edicts = number + 1;
758  }
759  }
760 }

Referenced by MVD_ParseFrame().

◆ MVD_ParsePacketPlayers()

static void MVD_ParsePacketPlayers ( mvd_t mvd)
static

Definition at line 767 of file parse.c.

768 {
769  int number;
770  int bits;
771  mvd_player_t *player;
772 
773  while (1) {
774  if (msg_read.readcount > msg_read.cursize) {
775  MVD_Destroyf(mvd, "%s: read past end of message", __func__);
776  }
777 
778  number = MSG_ReadByte();
779  if (number == CLIENTNUM_NONE) {
780  break;
781  }
782 
783  if (number < 0 || number >= mvd->maxclients) {
784  MVD_Destroyf(mvd, "%s: bad number: %d", __func__, number);
785  }
786 
787  player = &mvd->players[number];
788 
789  bits = MSG_ReadShort();
790 
791 #ifdef _DEBUG
792  if (mvd_shownet->integer > 2) {
793  Com_Printf(" %s: %d ", player->inuse ?
794  "delta" : "baseline", number);
795  MSG_ShowDeltaPlayerstateBits_Packet(bits);
796  Com_Printf("\n");
797  }
798 #endif
799 
800  MSG_ParseDeltaPlayerstate_Packet(&player->ps, &player->ps, bits);
801 
802  if (bits & PPS_REMOVE) {
803  SHOWNET(2, " remove: %d\n", number);
804  player->inuse = qfalse;
805  continue;
806  }
807 
808  player->inuse = qtrue;
809  }
810 }

Referenced by MVD_ParseFrame().

◆ MVD_ParsePrint()

static void MVD_ParsePrint ( mvd_t mvd)
static

Definition at line 645 of file parse.c.

646 {
647  int level;
648  char string[MAX_STRING_CHARS];
649 
650  level = MSG_ReadByte();
651  MSG_ReadString(string, sizeof(string));
652 
653  if (level == PRINT_HIGH && strstr(string, "Match ended.")) {
654  match_ended_hack = qtrue;
655  }
656 
657  if (mvd->demoseeking)
658  return;
659 
660  MVD_BroadcastPrintf(mvd, level, level == PRINT_CHAT ?
661  UF_MUTE_PLAYERS : 0, "%s", string);
662 }

Referenced by MVD_ParseMessage().

◆ MVD_ParseServerData()

static void MVD_ParseServerData ( mvd_t mvd,
int  extrabits 
)
static

Definition at line 936 of file parse.c.

937 {
938  int protocol;
939  size_t len, maxlen;
940  char *string;
941  int index;
942  qerror_t ret;
943  edict_t *ent;
944 
945  // clear the leftover from previous level
946  MVD_ClearState(mvd, qtrue);
947 
948  // parse major protocol version
949  protocol = MSG_ReadLong();
950  if (protocol != PROTOCOL_VERSION_MVD) {
951  MVD_Destroyf(mvd, "Unsupported protocol: %d", protocol);
952  }
953 
954  // parse minor protocol version
955  protocol = MSG_ReadShort();
956  if (!MVD_SUPPORTED(protocol)) {
957  MVD_Destroyf(mvd, "Unsupported MVD protocol version: %d.\n"
958  "Current version is %d.\n", protocol, PROTOCOL_VERSION_MVD_CURRENT);
959  }
960 
961  mvd->servercount = MSG_ReadLong();
962  len = MSG_ReadString(mvd->gamedir, sizeof(mvd->gamedir));
963  if (len >= sizeof(mvd->gamedir)) {
964  MVD_Destroyf(mvd, "Oversize gamedir string");
965  }
966  mvd->clientNum = MSG_ReadShort();
967  mvd->flags = extrabits;
968 
969 #if 0
970  // change gamedir unless playing a demo
971  Cvar_UserSet("game", mvd->gamedir);
972 #endif
973 
974  // parse configstrings
975  while (1) {
976  index = MSG_ReadShort();
977  if (index == MAX_CONFIGSTRINGS) {
978  break;
979  }
980 
981  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
982  MVD_Destroyf(mvd, "Bad configstring index: %d", index);
983  }
984 
985  string = mvd->configstrings[index];
986  maxlen = CS_SIZE(index);
987  len = MSG_ReadString(string, maxlen);
988  if (len >= maxlen) {
989  MVD_Destroyf(mvd, "Configstring %d overflowed", index);
990  }
991 
992  if (msg_read.readcount > msg_read.cursize) {
993  MVD_Destroyf(mvd, "Read past end of message");
994  }
995  }
996 
997  // parse maxclients
998  index = atoi(mvd->configstrings[CS_MAXCLIENTS]);
999  if (index < 1 || index > MAX_CLIENTS) {
1000  MVD_Destroyf(mvd, "Invalid maxclients");
1001  }
1002 
1003  // check if maxclients changed
1004  if (index != mvd->maxclients) {
1005  mvd_client_t *client;
1006 
1007  // free any old players
1008  Z_Free(mvd->players);
1009 
1010  // allocate new players
1011  mvd->players = MVD_Mallocz(sizeof(mvd_player_t) * index);
1012  mvd->maxclients = index;
1013 
1014  // clear chase targets
1015  FOR_EACH_MVDCL(client, mvd) {
1016  client->target = NULL;
1017  client->oldtarget = NULL;
1018  client->chase_mask = 0;
1019  client->chase_auto = qfalse;
1020  client->chase_wait = qfalse;
1021  memset(client->chase_bitmap, 0, sizeof(client->chase_bitmap));
1022  }
1023  }
1024 
1025  if (mvd->clientNum == -1) {
1026  mvd->dummy = NULL;
1027  } else {
1028  // validate clientNum
1029  if (mvd->clientNum < 0 || mvd->clientNum >= mvd->maxclients) {
1030  MVD_Destroyf(mvd, "Invalid client num: %d", mvd->clientNum);
1031  }
1032  mvd->dummy = mvd->players + mvd->clientNum;
1033  }
1034 
1035  // parse world model
1036  string = mvd->configstrings[CS_MODELS + 1];
1037  len = strlen(string);
1038  if (len <= 9) {
1039  MVD_Destroyf(mvd, "Bad world model: %s", string);
1040  }
1041  memcpy(mvd->mapname, string + 5, len - 9); // skip "maps/"
1042  mvd->mapname[len - 9] = 0; // cut off ".bsp"
1043 
1044  // load the world model (we are only interesed in visibility info)
1045  Com_Printf("[%s] -=- Loading %s...\n", mvd->name, string);
1046  ret = CM_LoadMap(&mvd->cm, string);
1047  if (ret) {
1048  Com_EPrintf("[%s] =!= Couldn't load %s: %s\n", mvd->name, string, Q_ErrorString(ret));
1049  // continue with null visibility
1050  }
1051 #if USE_MAPCHECKSUM
1052  else if (mvd->cm.cache->checksum != atoi(mvd->configstrings[CS_MAPCHECKSUM])) {
1053  Com_EPrintf("[%s] =!= Local map version differs from server!\n", mvd->name);
1054  CM_FreeMap(&mvd->cm);
1055  }
1056 #endif
1057 
1058  // set player names
1060 
1061  // init world entity
1062  ent = &mvd->edicts[0];
1063  ent->solid = SOLID_BSP;
1064  ent->inuse = qtrue;
1065 
1066  if (mvd->cm.cache) {
1067  // get the spawn point for spectators
1068  MVD_ParseEntityString(mvd, mvd->cm.cache->entitystring);
1069  }
1070 
1071  // parse baseline frame
1073 
1074  // save base configstrings
1075  memcpy(mvd->baseconfigstrings, mvd->configstrings, sizeof(mvd->baseconfigstrings));
1076 
1077  // force inital snapshot
1078  mvd->last_snapshot = INT_MIN;
1079 
1080  // if the channel has been just created, init some things
1081  if (!mvd->state) {
1082  mvd_t *cur;
1083 
1084  // sort this one into the list of active channels
1085  FOR_EACH_MVD(cur) {
1086  if (cur->id > mvd->id) {
1087  break;
1088  }
1089  }
1090  List_Append(&cur->entry, &mvd->entry);
1091  mvd->state = MVD_WAITING;
1092  }
1093 
1094  // case all UDP clients to reconnect
1096 }

Referenced by MVD_ParseMessage().

◆ MVD_ParseSound()

static void MVD_ParseSound ( mvd_t mvd,
int  extrabits 
)
static

Definition at line 487 of file parse.c.

488 {
489  int flags, index;
490  int volume, attenuation, offset, sendchan;
491  int entnum;
492  vec3_t origin;
493  mvd_client_t *client;
494  client_t *cl;
495  byte mask[VIS_MAX_BYTES];
496  mleaf_t *leaf;
497  int area;
498  player_state_t *ps;
500  edict_t *entity;
501  int i;
502 
503  flags = MSG_ReadByte();
504  index = MSG_ReadByte();
505 
506  volume = attenuation = offset = 0;
507  if (flags & SND_VOLUME)
508  volume = MSG_ReadByte();
509  if (flags & SND_ATTENUATION)
510  attenuation = MSG_ReadByte();
511  if (flags & SND_OFFSET)
512  offset = MSG_ReadByte();
513 
514  // entity relative
515  sendchan = MSG_ReadShort();
516  entnum = sendchan >> 3;
517  if (entnum < 0 || entnum >= MAX_EDICTS) {
518  MVD_Destroyf(mvd, "%s: bad entnum: %d", __func__, entnum);
519  }
520 
521  entity = &mvd->edicts[entnum];
522  if (!entity->inuse) {
523  Com_DPrintf("%s: entnum not in use: %d\n", __func__, entnum);
524  return;
525  }
526 
527  if (mvd->demoseeking)
528  return;
529 
530  FOR_EACH_MVDCL(client, mvd) {
531  cl = client->cl;
532 
533  // do not send unreliables to connecting clients
534  if (cl->state != cs_spawned || cl->download || cl->nodata) {
535  continue;
536  }
537 
538  // PHS cull this sound
539  if (!(extrabits & 1)) {
540  // get client viewpos
541  ps = &client->ps;
542  VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin, origin);
543  leaf = CM_PointLeaf(&mvd->cm, origin);
544  area = CM_LeafArea(leaf);
545  if (!CM_AreasConnected(&mvd->cm, area, entity->areanum)) {
546  // doors can legally straddle two areas, so
547  // we may need to check another one
548  if (!entity->areanum2 || !CM_AreasConnected(&mvd->cm, area, entity->areanum2)) {
549  continue; // blocked by a door
550  }
551  }
552  BSP_ClusterVis(mvd->cm.cache, mask, leaf->cluster, DVIS_PHS);
553  if (!SV_EdictIsVisible(&mvd->cm, entity, mask)) {
554  continue; // not in PHS
555  }
556  }
557 
558  // use the entity origin unless it is a bmodel
559  if (entity->solid == SOLID_BSP) {
560  VectorAvg(entity->mins, entity->maxs, origin);
561  VectorAdd(entity->s.origin, origin, origin);
562  } else {
563  VectorCopy(entity->s.origin, origin);
564  }
565 
566  // reliable sounds will always have position explicitly set,
567  // as no one gurantees reliables to be delivered in time
568  if (extrabits & 2) {
569  MSG_WriteByte(svc_sound);
570  MSG_WriteByte(flags | SND_POS);
571  MSG_WriteByte(index);
572 
573  if (flags & SND_VOLUME)
574  MSG_WriteByte(volume);
575  if (flags & SND_ATTENUATION)
576  MSG_WriteByte(attenuation);
577  if (flags & SND_OFFSET)
578  MSG_WriteByte(offset);
579 
580  MSG_WriteShort(sendchan);
582 
584  continue;
585  }
586 
587  if (LIST_EMPTY(&cl->msg_free_list)) {
588  Com_WPrintf("%s: %s: out of message slots\n",
589  __func__, cl->name);
590  continue;
591  }
592 
593  // default client doesn't know that bmodels have weird origins
594  if (entity->solid == SOLID_BSP && cl->protocol == PROTOCOL_VERSION_DEFAULT) {
595  flags |= SND_POS;
596  }
597 
598  msg = LIST_FIRST(message_packet_t, &cl->msg_free_list, entry);
599 
600  msg->cursize = 0;
601  msg->flags = flags;
602  msg->index = index;
603  msg->volume = volume;
604  msg->attenuation = attenuation;
605  msg->timeofs = offset;
606  msg->sendchan = sendchan;
607  for (i = 0; i < 3; i++) {
608  msg->pos[i] = origin[i] * 8;
609  }
610 
611  List_Remove(&msg->entry);
612  List_Append(&cl->msg_unreliable_list, &msg->entry);
613  cl->msg_unreliable_bytes += MAX_SOUND_PACKET;
614 
615  flags &= ~SND_POS;
616  }
617 }

Referenced by MVD_ParseMessage().

◆ MVD_ParseUnicast()

static void MVD_ParseUnicast ( mvd_t mvd,
mvd_ops_t  op,
int  extrabits 
)
static

Definition at line 413 of file parse.c.

414 {
415  int clientNum;
416  size_t length, last;
417  mvd_player_t *player;
418  byte *data;
419  qboolean reliable;
420  int cmd;
421 
422  length = MSG_ReadByte();
423  length |= extrabits << 8;
424  clientNum = MSG_ReadByte();
425 
426  if (clientNum < 0 || clientNum >= mvd->maxclients) {
427  MVD_Destroyf(mvd, "%s: bad number: %d", __func__, clientNum);
428  }
429 
430  last = msg_read.readcount + length;
431  if (last > msg_read.cursize) {
432  MVD_Destroyf(mvd, "%s: read past end of message", __func__);
433  }
434 
435  player = &mvd->players[clientNum];
436 
437  reliable = op == mvd_unicast_r ? qtrue : qfalse;
438 
439  while (msg_read.readcount < last) {
440  cmd = MSG_ReadByte();
441 #ifdef _DEBUG
442  if (mvd_shownet->integer > 1) {
443  MSG_ShowSVC(cmd);
444  }
445 #endif
446  switch (cmd) {
447  case svc_layout:
448  MVD_UnicastLayout(mvd, player);
449  break;
450  case svc_configstring:
451  MVD_UnicastString(mvd, reliable, player);
452  break;
453  case svc_print:
454  MVD_UnicastPrint(mvd, reliable, player);
455  break;
456  case svc_stufftext:
457  MVD_UnicastStuff(mvd, reliable, player);
458  break;
459  default:
460  SHOWNET(1, "%"PRIz":SKIPPING UNICAST\n", msg_read.readcount - 1);
461  // send remaining data and return
462  data = msg_read.data + msg_read.readcount - 1;
463  length = last - msg_read.readcount + 1;
464  if (!mvd->demoseeking)
465  MVD_UnicastSend(mvd, reliable, data, length, player);
466  msg_read.readcount = last;
467  return;
468  }
469  }
470 
471  SHOWNET(1, "%"PRIz":END OF UNICAST\n", msg_read.readcount - 1);
472 
473  if (msg_read.readcount > last) {
474  MVD_Destroyf(mvd, "%s: read past end of unicast", __func__);
475  }
476 }

Referenced by MVD_ParseMessage().

◆ MVD_PlayerToEntityStates()

static void MVD_PlayerToEntityStates ( mvd_t mvd)
static

Definition at line 668 of file parse.c.

669 {
670  mvd_player_t *player;
671  edict_t *edict;
672  int i;
673 
674  mvd->numplayers = 0;
675  for (i = 1, player = mvd->players; i <= mvd->maxclients; i++, player++) {
676  if (!player->inuse || player == mvd->dummy) {
677  continue;
678  }
679 
680  mvd->numplayers++;
681  if (player->ps.pmove.pm_type != PM_NORMAL) {
682  continue; // can be out of sync, in this case
683  // server should provide valid data
684  }
685 
686  edict = &mvd->edicts[i];
687  if (!edict->inuse) {
688  continue; // not present in this frame
689  }
690 
691  Com_PlayerToEntityState(&player->ps, &edict->s);
692 
693  MVD_LinkEdict(mvd, edict);
694  }
695 }

Referenced by MVD_ParseFrame().

◆ MVD_UnicastLayout()

static void MVD_UnicastLayout ( mvd_t mvd,
mvd_player_t player 
)
static

Definition at line 266 of file parse.c.

267 {
268  mvd_client_t *client;
269 
270  if (mvd->dummy && player != mvd->dummy) {
271  MSG_ReadString(NULL, 0);
272  return; // we don't care about others
273  }
274 
275  MSG_ReadString(mvd->layout, sizeof(mvd->layout));
276 
277  // HACK: if we got "match ended" string this frame, save oldscores
278  if (match_ended_hack) {
279  strcpy(mvd->oldscores, mvd->layout);
280  }
281 
282  if (mvd->demoseeking)
283  return;
284 
285  // force an update to all relevant clients
286  FOR_EACH_MVDCL(client, mvd) {
287  if (client->cl->state < cs_spawned) {
288  continue;
289  }
290  if (client->layout_type == LAYOUT_SCORES) {
291  client->layout_time = 0;
292  }
293  }
294 }

Referenced by MVD_ParseUnicast().

◆ MVD_UnicastPrint()

static void MVD_UnicastPrint ( mvd_t mvd,
qboolean  reliable,
mvd_player_t player 
)
static

Definition at line 343 of file parse.c.

344 {
345  int level;
346  byte *data;
347  size_t readcount, length;
348  mvd_client_t *client;
349  client_t *cl;
350  mvd_player_t *target;
351 
352  data = msg_read.data + msg_read.readcount - 1;
353  readcount = msg_read.readcount - 1;
354 
355  level = MSG_ReadByte();
356  MSG_ReadString(NULL, 0);
357 
358  if (mvd->demoseeking)
359  return;
360 
361  length = msg_read.readcount - readcount;
362 
363  // send to all relevant clients
364  FOR_EACH_MVDCL(client, mvd) {
365  cl = client->cl;
366  if (cl->state < cs_spawned) {
367  continue;
368  }
369  if (level < cl->messagelevel) {
370  continue;
371  }
372  if (level == PRINT_CHAT && (client->uf & UF_MUTE_PLAYERS)) {
373  continue;
374  }
375  // decide if message should be routed or not
376  target = (mvd->flags & MVF_NOMSGS) ? mvd->dummy :
377  client->target ? client->target : mvd->dummy;
378  if (target == player) {
379  cl->AddMessage(cl, data, length, reliable);
380  }
381  }
382 }

Referenced by MVD_ParseUnicast().

◆ MVD_UnicastSend()

static void MVD_UnicastSend ( mvd_t mvd,
qboolean  reliable,
byte *  data,
size_t  length,
mvd_player_t player 
)
static

Definition at line 247 of file parse.c.

248 {
249  mvd_player_t *target;
250  mvd_client_t *client;
251  client_t *cl;
252 
253  // send to all relevant clients
254  FOR_EACH_MVDCL(client, mvd) {
255  cl = client->cl;
256  if (cl->state < cs_spawned) {
257  continue;
258  }
259  target = client->target ? client->target : mvd->dummy;
260  if (target == player) {
261  cl->AddMessage(cl, data, length, reliable);
262  }
263  }
264 }

Referenced by MVD_ParseUnicast(), MVD_UnicastString(), and MVD_UnicastStuff().

◆ MVD_UnicastString()

static void MVD_UnicastString ( mvd_t mvd,
qboolean  reliable,
mvd_player_t player 
)
static

Definition at line 296 of file parse.c.

297 {
298  int index;
299  char string[MAX_QPATH];
300  mvd_cs_t *cs;
301  byte *data;
302  size_t readcount, length;
303 
304  data = msg_read.data + msg_read.readcount - 1;
305  readcount = msg_read.readcount - 1;
306 
307  index = MSG_ReadShort();
308  length = MSG_ReadString(string, sizeof(string));
309 
310  if (index < 0 || index >= MAX_CONFIGSTRINGS) {
311  MVD_Destroyf(mvd, "%s: bad index: %d", __func__, index);
312  }
313  if (index < CS_GENERAL) {
314  Com_DPrintf("%s: common configstring: %d\n", __func__, index);
315  return;
316  }
317  if (length >= sizeof(string)) {
318  Com_DPrintf("%s: oversize configstring: %d\n", __func__, index);
319  return;
320  }
321 
322  for (cs = player->configstrings; cs; cs = cs->next) {
323  if (cs->index == index) {
324  break;
325  }
326  }
327  if (!cs) {
328  cs = MVD_Malloc(sizeof(*cs) + MAX_QPATH - 1);
329  cs->index = index;
330  cs->next = player->configstrings;
331  player->configstrings = cs;
332  }
333 
334  memcpy(cs->string, string, length + 1);
335 
336  if (mvd->demoseeking)
337  return;
338 
339  length = msg_read.readcount - readcount;
340  MVD_UnicastSend(mvd, reliable, data, length, player);
341 }

Referenced by MVD_ParseUnicast().

◆ MVD_UnicastStuff()

static void MVD_UnicastStuff ( mvd_t mvd,
qboolean  reliable,
mvd_player_t player 
)
static

Definition at line 384 of file parse.c.

385 {
386  char string[8];
387  byte *data;
388  size_t readcount, length;
389 
390  if (mvd->demoseeking) {
391  MSG_ReadString(NULL, 0);
392  return;
393  }
394 
395  data = msg_read.data + msg_read.readcount - 1;
396  readcount = msg_read.readcount - 1;
397 
398  MSG_ReadString(string, sizeof(string));
399  if (strncmp(string, "play ", 5)) {
400  return;
401  }
402 
403  length = msg_read.readcount - readcount;
404  MVD_UnicastSend(mvd, reliable, data, length, player);
405 }

Referenced by MVD_ParseUnicast().

Variable Documentation

◆ match_ended_hack

qboolean match_ended_hack
static

Definition at line 26 of file parse.c.

Referenced by MVD_ParseMessage(), MVD_ParsePrint(), and MVD_UnicastLayout().

mvd_player_t::configstrings
mvd_cs_t * configstrings
Definition: client.h:66
MVD_ClearState
void MVD_ClearState(mvd_t *mvd, qboolean full)
Definition: parse.c:856
mvd_client_t::layout_time
unsigned layout_time
Definition: client.h:93
CM_FreeMap
void CM_FreeMap(cm_t *cm)
Definition: cmodel.c:47
MVD_SPAWN_INTERNAL
#define MVD_SPAWN_INTERNAL
Definition: server.h:96
RELINK_MASK
#define RELINK_MASK
Definition: parse.c:697
cs_spawned
@ cs_spawned
Definition: server.h:192
mvd_server_t::players
player_packed_t * players
Definition: mvd.c:69
MVD_Spawn
void MVD_Spawn(void)
Definition: client.c:1653
mvd_client_t::chase_bitmap
byte chase_bitmap[MAX_CLIENTS/CHAR_BIT]
Definition: client.h:90
msg_read
sizebuf_t msg_read
Definition: msg.c:37
match_ended_hack
static qboolean match_ended_hack
Definition: parse.c:26
maxclients
cvar_t * maxclients
Definition: g_main.c:42
CM_LoadMap
qerror_t CM_LoadMap(cm_t *cm, const char *name)
Definition: cmodel.c:64
message_packet_t
Definition: server.h:220
MVD_UnicastPrint
static void MVD_UnicastPrint(mvd_t *mvd, qboolean reliable, mvd_player_t *player)
Definition: parse.c:343
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
mvd_client_t::chase_mask
int chase_mask
Definition: client.h:87
BSP_ClusterVis
byte * BSP_ClusterVis(bsp_t *bsp, byte *mask, int cluster, int vis)
Definition: bsp.c:1339
client_s::state
clstate_t state
Definition: server.h:260
MSG_CLEAR
#define MSG_CLEAR
Definition: server.h:215
mvd_cs_s::string
char string[1]
Definition: client.h:59
MSG_RELIABLE
#define MSG_RELIABLE
Definition: server.h:214
MSG_ReadWord
int MSG_ReadWord(void)
Definition: msg.c:1503
client_s::spawncount
int spawncount
Definition: server.h:348
MVD_UpdateConfigstring
void MVD_UpdateConfigstring(mvd_t *mvd, int index)
Definition: game.c:1616
Com_PlayerToEntityState
void Com_PlayerToEntityState(const player_state_t *ps, entity_state_t *es)
Definition: utils.c:269
LAYOUT_SCORES
@ LAYOUT_SCORES
Definition: client.h:46
mvd_snap_t
Definition: client.h:115
mvd_client_t::layout_type
mvd_layout_t layout_type
Definition: client.h:92
mvd_dirty
qboolean mvd_dirty
Definition: client.c:102
mvd_s::id
int id
Definition: client.h:131
SHOWNET
#define SHOWNET(...)
Definition: parse.c:61
FOR_EACH_MVD
#define FOR_EACH_MVD(mvd)
Definition: client.h:26
MSG_WriteByte
void MSG_WriteByte(int c)
Definition: msg.c:107
svc_stufftext
#define svc_stufftext
Definition: g_local.h:41
mvd_client_t::uf
int uf
Definition: client.h:83
SV_ClientAddMessage
void SV_ClientAddMessage(client_t *client, int flags)
Definition: send.c:399
mvd_cs_s::index
int index
Definition: client.h:58
MVD_ParseServerData
static void MVD_ParseServerData(mvd_t *mvd, int extrabits)
Definition: parse.c:936
CM_AreasConnected
qboolean CM_AreasConnected(cm_t *cm, int area1, int area2)
Definition: cmodel.c:890
MSG_WritePos
void MSG_WritePos(const vec3_t pos)
Definition: msg.c:198
MVD_ParseMulticast
static void MVD_ParseMulticast(mvd_t *mvd, mvd_ops_t op, int extrabits)
Definition: parse.c:152
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
mvd_player_t::inuse
qboolean inuse
Definition: client.h:64
mvd_s
Definition: client.h:127
SV_SendAsyncPackets
void SV_SendAsyncPackets(void)
Definition: send.c:987
sv
server_t sv
Definition: init.c:22
mvd
static mvd_server_t mvd
Definition: mvd.c:81
msg_write
sizebuf_t msg_write
Definition: msg.c:34
mvd_client_t::target
mvd_player_t * target
Definition: client.h:85
va
char * va(const char *format,...)
Definition: shared.c:429
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
MVD_ChangeLevel
static void MVD_ChangeLevel(mvd_t *mvd)
Definition: parse.c:901
MSG_ReadLong
int MSG_ReadLong(void)
Definition: msg.c:1517
MVD_ParseUnicast
static void MVD_ParseUnicast(mvd_t *mvd, mvd_ops_t op, int extrabits)
Definition: parse.c:413
origin
static vec3_t origin
Definition: mesh.c:27
MVD_UnicastStuff
static void MVD_UnicastStuff(mvd_t *mvd, qboolean reliable, mvd_player_t *player)
Definition: parse.c:384
MVD_UnicastLayout
static void MVD_UnicastLayout(mvd_t *mvd, mvd_player_t *player)
Definition: parse.c:266
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
mvd_client_t::oldtarget
mvd_player_t * oldtarget
Definition: client.h:86
mvd_client_t::cl
client_t * cl
Definition: client.h:78
MSG_WriteShort
void MSG_WriteShort(int c)
Definition: msg.c:125
MVD_ParsePacketPlayers
static void MVD_ParsePacketPlayers(mvd_t *mvd)
Definition: parse.c:767
MVD_WAITING
@ MVD_WAITING
Definition: client.h:109
mvd_client_t
Definition: client.h:69
MVD_LinkEdict
void MVD_LinkEdict(mvd_t *mvd, edict_t *ent)
Definition: game.c:1652
MVD_SetPlayerNames
void MVD_SetPlayerNames(mvd_t *mvd)
Definition: game.c:1607
Cvar_UserSet
cvar_t * Cvar_UserSet(const char *var_name, const char *value)
Definition: cvar.c:476
MVD_ParsePacketEntities
static void MVD_ParsePacketEntities(mvd_t *mvd)
Definition: parse.c:704
MVD_Malloc
#define MVD_Malloc(size)
Definition: client.h:22
FOR_EACH_MVDCL
#define FOR_EACH_MVDCL(cl, mvd)
Definition: client.h:29
mvd_client_t::ps
player_state_t ps
Definition: client.h:71
cl
client_state_t cl
Definition: main.c:99
mvd_cs_s
Definition: client.h:56
mvd_server_t::dummy
client_t * dummy
Definition: mvd.c:57
MVD_ParseEntityString
void MVD_ParseEntityString(mvd_t *mvd, const char *data)
Definition: parse.c:64
mvd_client_t::chase_auto
qboolean chase_auto
Definition: client.h:88
MSG_WriteString
void MSG_WriteString(const char *string)
Definition: msg.c:160
MVD_ParseConfigstring
static void MVD_ParseConfigstring(mvd_t *mvd)
Definition: parse.c:619
mvd_client_t::chase_wait
qboolean chase_wait
Definition: client.h:89
mvd_player_t
Definition: client.h:62
MVD_UpdateClients
void MVD_UpdateClients(mvd_t *mvd)
Definition: game.c:2175
CM_PointLeaf
mleaf_t * CM_PointLeaf(cm_t *cm, vec3_t p)
Definition: cmodel.c:209
MAX_SOUND_PACKET
#define MAX_SOUND_PACKET
Definition: server.h:218
SV_InitGame
void SV_InitGame(unsigned mvd_spawn)
Definition: init.c:361
MSG_ReadString
size_t MSG_ReadString(char *dest, size_t size)
Definition: msg.c:1531
MVD_UnicastSend
static void MVD_UnicastSend(mvd_t *mvd, qboolean reliable, byte *data, size_t length, mvd_player_t *player)
Definition: parse.c:247
mvd_cs_s::next
struct mvd_cs_s * next
Definition: client.h:57
level
level_locals_t level
Definition: g_main.c:22
cs_primed
@ cs_primed
Definition: server.h:191
server_t::state
server_state_t state
Definition: server.h:146
msg
const char * msg
Definition: win.h:25
CM_LeafNum
mleaf_t * CM_LeafNum(cm_t *cm, int number)
Definition: cmodel.c:98
client_s
Definition: server.h:256
MVD_ParseFrame
static void MVD_ParseFrame(mvd_t *mvd)
Definition: parse.c:817
svc_layout
#define svc_layout
Definition: g_local.h:39
COM_Parse
char * COM_Parse(const char **data_p)
Definition: shared.c:455
MVD_BroadcastPrintf
void MVD_BroadcastPrintf(mvd_t *mvd, int level, int mask, const char *fmt,...) q_printf(4
MVD_UnicastString
static void MVD_UnicastString(mvd_t *mvd, qboolean reliable, mvd_player_t *player)
Definition: parse.c:296
MVD_FreePlayer
void MVD_FreePlayer(mvd_player_t *player)
Definition: game.c:1540
MSG_ReadByte
int MSG_ReadByte(void)
Definition: msg.c:1475
SV_EdictIsVisible
qboolean SV_EdictIsVisible(cm_t *cm, edict_t *ent, byte *mask)
Definition: world.c:129
mvd_player_t::ps
player_state_t ps
Definition: client.h:63
CM_SetPortalStates
void CM_SetPortalStates(cm_t *cm, byte *buffer, int bytes)
Definition: cmodel.c:982
MVD_PlayerToEntityStates
static void MVD_PlayerToEntityStates(mvd_t *mvd)
Definition: parse.c:668
MVD_Destroyf
void MVD_Destroyf(mvd_t *mvd, const char *fmt,...)
Definition: client.c:191
MVD_ParseSound
static void MVD_ParseSound(mvd_t *mvd, int extrabits)
Definition: parse.c:487
SZ_Clear
void SZ_Clear(sizebuf_t *buf)
Definition: sizebuf.c:40
MVD_Mallocz
#define MVD_Mallocz(size)
Definition: client.h:23
SV_ClientReset
void SV_ClientReset(client_t *client)
Definition: init.c:24
mvd_s::entry
list_t entry
Definition: client.h:128
MVD_ParsePrint
static void MVD_ParsePrint(mvd_t *mvd)
Definition: parse.c:645
MSG_ReadShort
int MSG_ReadShort(void)
Definition: msg.c:1489