24 #include "server/mvd/protocol.h"
29 #define SHOWNET(level, ...) \
30 if (mvd_shownet->integer > level) \
31 Com_LPrintf(PRINT_DEVELOPER, __VA_ARGS__)
33 #define MVD_ShowSVC(cmd) \
34 Com_Printf("%3"PRIz":%s\n", msg_read.readcount - 1, MVD_ServerCommandString(cmd))
36 static const char *MVD_ServerCommandString(
int cmd)
39 case -1:
return "END OF MESSAGE";
40 default:
return "UNKNOWN COMMAND";
42 case mvd_##x: return "mvd_" #x;
67 char key[MAX_STRING_CHARS];
68 char value[MAX_STRING_CHARS];
69 char classname[MAX_QPATH];
79 Com_Error(ERR_DROP,
"expected '{', found '%s'", p);
91 Com_Error(ERR_DROP,
"expected key, found '{'");
98 Com_Error(ERR_DROP,
"expected key/value pair, found EOF");
100 if (p[0] ==
'}' || p[0] ==
'{') {
101 Com_Error(ERR_DROP,
"expected value, found '%s'", p);
104 if (!strcmp(key,
"classname")) {
105 Q_strlcpy(classname, p,
sizeof(classname));
112 if (!strcmp(key,
"origin")) {
116 }
else if (!strncmp(key,
"angle", 5)) {
121 }
else if (key[5] ==
's' && key[6] == 0) {
130 Com_Error(ERR_DROP,
"entity with no classname");
133 if (strncmp(classname,
"info_player_", 12)) {
137 if (!strcmp(classname + 12,
"intermission")) {
139 VectorCopy(angles,
mvd->spawnAngles);
143 if (!strcmp(classname + 12,
"start") ||
144 !strcmp(classname + 12,
"deathmatch")) {
146 VectorCopy(angles,
mvd->spawnAngles);
156 byte mask[VIS_MAX_BYTES];
157 mleaf_t *leaf1, *leaf2;
159 qboolean reliable = qfalse;
165 length |= extrabits << 8;
168 case mvd_multicast_all_r:
171 case mvd_multicast_all:
174 case mvd_multicast_phs_r:
177 case mvd_multicast_phs:
179 if (
mvd->demoseeking) {
186 case mvd_multicast_pvs_r:
189 case mvd_multicast_pvs:
191 if (
mvd->demoseeking) {
209 if (
mvd->demoseeking)
228 VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin, org);
232 VectorScale(ps->pmove.origin, 0.125f, org);
237 if (leaf2->cluster == -1)
239 if (!Q_IsBitSet(mask, leaf2->cluster))
243 cl->AddMessage(
cl, data, length, reliable);
260 if (target == player) {
261 cl->AddMessage(
cl, data, length, reliable);
279 strcpy(
mvd->oldscores,
mvd->layout);
282 if (
mvd->demoseeking)
299 char string[MAX_QPATH];
302 size_t readcount, length;
310 if (index < 0 || index >= MAX_CONFIGSTRINGS) {
313 if (index < CS_GENERAL) {
314 Com_DPrintf(
"%s: common configstring: %d\n", __func__, index);
317 if (length >=
sizeof(
string)) {
318 Com_DPrintf(
"%s: oversize configstring: %d\n", __func__, index);
323 if (cs->
index == index) {
334 memcpy(cs->
string,
string, length + 1);
336 if (
mvd->demoseeking)
339 length =
msg_read.readcount - readcount;
347 size_t readcount, length;
358 if (
mvd->demoseeking)
361 length =
msg_read.readcount - readcount;
369 if (level < cl->messagelevel) {
372 if (
level == PRINT_CHAT && (client->
uf & UF_MUTE_PLAYERS)) {
378 if (target == player) {
379 cl->AddMessage(
cl, data, length, reliable);
388 size_t readcount, length;
390 if (
mvd->demoseeking) {
399 if (strncmp(
string,
"play ", 5)) {
403 length =
msg_read.readcount - readcount;
423 length |= extrabits << 8;
426 if (clientNum < 0 || clientNum >=
mvd->maxclients) {
437 reliable = op == mvd_unicast_r ? qtrue : qfalse;
442 if (mvd_shownet->integer > 1) {
450 case svc_configstring:
463 length = last -
msg_read.readcount + 1;
464 if (!
mvd->demoseeking)
490 int volume, attenuation, offset, sendchan;
495 byte mask[VIS_MAX_BYTES];
506 volume = attenuation = offset = 0;
507 if (flags & SND_VOLUME)
509 if (flags & SND_ATTENUATION)
511 if (flags & SND_OFFSET)
516 entnum = sendchan >> 3;
517 if (entnum < 0 || entnum >= MAX_EDICTS) {
521 entity = &
mvd->edicts[entnum];
522 if (!entity->inuse) {
523 Com_DPrintf(
"%s: entnum not in use: %d\n", __func__, entnum);
527 if (
mvd->demoseeking)
539 if (!(extrabits & 1)) {
542 VectorMA(ps->viewoffset, 0.125f, ps->pmove.origin,
origin);
544 area = CM_LeafArea(leaf);
559 if (entity->solid == SOLID_BSP) {
560 VectorAvg(entity->mins, entity->maxs,
origin);
563 VectorCopy(entity->s.origin,
origin);
573 if (flags & SND_VOLUME)
575 if (flags & SND_ATTENUATION)
577 if (flags & SND_OFFSET)
587 if (LIST_EMPTY(&
cl->msg_free_list)) {
588 Com_WPrintf(
"%s: %s: out of message slots\n",
594 if (entity->solid == SOLID_BSP &&
cl->protocol == PROTOCOL_VERSION_DEFAULT) {
603 msg->volume = volume;
604 msg->attenuation = attenuation;
605 msg->timeofs = offset;
606 msg->sendchan = sendchan;
607 for (i = 0; i < 3; i++) {
611 List_Remove(&
msg->entry);
612 List_Append(&
cl->msg_unreliable_list, &
msg->entry);
626 if (index < 0 || index >= MAX_CONFIGSTRINGS) {
630 s =
mvd->configstrings[index];
631 maxlen = CS_SIZE(index);
637 if (
mvd->demoseeking) {
638 Q_SetBit(
mvd->dcs, index);
648 char string[MAX_STRING_CHARS];
653 if (
level == PRINT_HIGH && strstr(
string,
"Match ended.")) {
657 if (
mvd->demoseeking)
661 UF_MUTE_PLAYERS : 0,
"%s",
string);
681 if (player->
ps.pmove.pm_type != PM_NORMAL) {
686 edict = &
mvd->edicts[i];
697 #define RELINK_MASK (U_MODEL|U_ORIGIN1|U_ORIGIN2|U_ORIGIN3|U_SOLID)
715 number = MSG_ParseEntityBits(&bits);
716 if (number < 0 || number >= MAX_EDICTS) {
724 ent = &
mvd->edicts[number];
727 if (mvd_shownet->integer > 2) {
728 Com_Printf(
" %s: %d ", ent->inuse ?
729 "delta" :
"baseline", number);
730 MSG_ShowDeltaEntityBits(bits);
735 MSG_ParseDeltaEntity(&ent->s, &ent->s, number, bits, 0);
743 ent->svflags |= SVF_MONSTER;
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);
756 if (number >=
mvd->pool.num_edicts) {
757 mvd->pool.num_edicts = number + 1;
779 if (number == CLIENTNUM_NONE) {
783 if (number < 0 || number >=
mvd->maxclients) {
792 if (mvd_shownet->integer > 2) {
793 Com_Printf(
" %s: %d ", player->
inuse ?
794 "delta" :
"baseline", number);
795 MSG_ShowDeltaPlayerstateBits_Packet(bits);
800 MSG_ParseDeltaPlayerstate_Packet(&player->
ps, &player->
ps, bits);
802 if (bits & PPS_REMOVE) {
803 SHOWNET(2,
" remove: %d\n", number);
804 player->
inuse = qfalse;
808 player->
inuse = qtrue;
825 if (length < 0 || msg_read.readcount + length >
msg_read.cursize) {
828 if (length > MAX_MAP_PORTAL_BYTES) {
837 if (!
mvd->demoseeking)
849 if (
mvd->state &&
mvd->framenum && !
mvd->demoseeking) {
864 memset(
mvd->edicts, 0,
sizeof(
mvd->edicts));
865 mvd->pool.num_edicts = 0;
868 for (i = 0; i <
mvd->maxclients; i++) {
871 memset(player, 0,
sizeof(*player));
880 LIST_FOR_EACH_SAFE(
mvd_snap_t, snap, next, &
mvd->snapshots, entry) {
884 List_Init(&
mvd->snapshots);
889 if (
mvd->intermission) {
894 memset(
mvd->configstrings, 0,
sizeof(
mvd->configstrings));
905 if (
sv.
state != ss_broadcast) {
929 mvd->intermission = qfalse;
950 if (protocol != PROTOCOL_VERSION_MVD) {
956 if (!MVD_SUPPORTED(protocol)) {
958 "Current version is %d.\n", protocol, PROTOCOL_VERSION_MVD_CURRENT);
963 if (len >=
sizeof(
mvd->gamedir)) {
967 mvd->flags = extrabits;
977 if (index == MAX_CONFIGSTRINGS) {
981 if (index < 0 || index >= MAX_CONFIGSTRINGS) {
985 string =
mvd->configstrings[index];
986 maxlen = CS_SIZE(index);
998 index = atoi(
mvd->configstrings[CS_MAXCLIENTS]);
999 if (index < 1 || index > MAX_CLIENTS) {
1004 if (index !=
mvd->maxclients) {
1012 mvd->maxclients = index;
1025 if (
mvd->clientNum == -1) {
1029 if (
mvd->clientNum < 0 ||
mvd->clientNum >=
mvd->maxclients) {
1036 string =
mvd->configstrings[CS_MODELS + 1];
1037 len = strlen(
string);
1041 memcpy(
mvd->mapname,
string + 5, len - 9);
1042 mvd->mapname[len - 9] = 0;
1045 Com_Printf(
"[%s] -=- Loading %s...\n",
mvd->name,
string);
1048 Com_EPrintf(
"[%s] =!= Couldn't load %s: %s\n",
mvd->name,
string,
Q_ErrorString(ret));
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);
1062 ent = &
mvd->edicts[0];
1063 ent->solid = SOLID_BSP;
1066 if (
mvd->cm.cache) {
1075 memcpy(
mvd->baseconfigstrings,
mvd->configstrings,
sizeof(
mvd->baseconfigstrings));
1078 mvd->last_snapshot = INT_MIN;
1086 if (cur->
id >
mvd->id) {
1090 List_Append(&cur->
entry, &
mvd->entry);
1101 qboolean ret = qfalse;
1104 if (mvd_shownet->integer == 1) {
1105 Com_Printf(
"%"PRIz
" ",
msg_read.cursize);
1106 }
else if (mvd_shownet->integer > 1) {
1107 Com_Printf(
"------------------\n");
1125 extrabits = cmd >> SVCMD_BITS;
1129 if (mvd_shownet->integer > 1) {
1135 case mvd_serverdata:
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:
1151 case mvd_configstring: