From edb540cd6ebb8411b18f12ce8c0ca34f40e3fdd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 7 Nov 2001 08:31:04 +0000 Subject: [PATCH] This completes the move of the networking code to its own branch allowing two conflicting developement tracks to better co-exist. To work on this brance, use "cvs up -r net_svc" and then update and commit as normal: committing to the branche will be automatic once the branch is checked out. Again: cvs up -r net_svc --- qw/include/bothdefs.h | 3 +- qw/include/cl_ents.h | 3 +- qw/include/client.h | 2 +- qw/include/host.h | 1 + qw/include/net.h | 2 + qw/include/protocol.h | 16 + qw/include/server.h | 2 +- qw/source/Makefile.am | 2 +- qw/source/cl_demo.c | 4 +- qw/source/cl_ents.c | 424 ++++++------- qw/source/cl_main.c | 28 + qw/source/cl_parse.c | 1238 +++++++++++++++++++++---------------- qw/source/cl_skin.c | 2 +- qw/source/cl_tent.c | 170 +++-- qw/source/cl_view.c | 29 +- qw/source/net_packetlog.c | 204 ++---- qw/source/sv_ccmds.c | 8 +- qw/source/sv_ents.c | 317 +++++----- qw/source/sv_init.c | 24 +- qw/source/sv_main.c | 34 +- qw/source/sv_model.c | 1 - qw/source/sv_phys.c | 6 +- qw/source/sv_pr_cmds.c | 61 +- qw/source/sv_send.c | 83 +-- qw/source/sv_user.c | 190 +++--- 25 files changed, 1495 insertions(+), 1359 deletions(-) diff --git a/qw/include/bothdefs.h b/qw/include/bothdefs.h index fb91221e3..8879cfbe1 100644 --- a/qw/include/bothdefs.h +++ b/qw/include/bothdefs.h @@ -62,11 +62,10 @@ #define MAX_LIGHTSTYLES 64 #define MAX_MODELS 256 // these are sent over the net as bytes #define MAX_SOUNDS 256 // so they cannot be blindly increased +#define MAX_PROJECTILES 32 #define SAVEGAME_COMMENT_LENGTH 39 -#define MAX_STYLESTRING 64 - // // stats are integers communicated to the client by the server // diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index ec1196f90..6e33e45a8 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -36,7 +36,8 @@ void CL_SetUpPlayerPrediction(qboolean dopred); void CL_EmitEntities (void); void CL_ClearProjectiles (void); void CL_ParseProjectiles (void); -void CL_ParsePacketEntities (qboolean delta); +void CL_ParsePacketEntities (void); +void CL_ParseDeltaPacketEntities (); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); diff --git a/qw/include/client.h b/qw/include/client.h index 8f4c52bb0..3c6415456 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -338,7 +338,7 @@ void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); -void V_ParseDamage (void); +void CL_ParseDamage (void); void V_PrepBlend (void); diff --git a/qw/include/host.h b/qw/include/host.h index 9fa3a7150..cc1b77a1b 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -60,6 +60,7 @@ void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void); void Host_Error (const char *error, ...) __attribute__((format(printf,1,2))); +void Host_NetError (const char *error, ...) __attribute((format(printf,1,2))); void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2))); void Host_Frame (float time); void Host_Quit_f (void); diff --git a/qw/include/net.h b/qw/include/net.h index b126ca181..34c67dee9 100644 --- a/qw/include/net.h +++ b/qw/include/net.h @@ -138,6 +138,8 @@ int Net_Log_Init (const char **sound_precache); void Log_Incoming_Packet (const char *p, int len); void Log_Outgoing_Packet (const char *p, int len); void Net_LogStop (void); +void Analyze_Server_Packet (const byte *data, int len); +void Analyze_Client_Packet (const byte *data, int len); extern struct cvar_s *net_packetlog; diff --git a/qw/include/protocol.h b/qw/include/protocol.h index b6c24765c..665fdb71e 100644 --- a/qw/include/protocol.h +++ b/qw/include/protocol.h @@ -214,6 +214,22 @@ #define U_UNUSED30 (1<<30) // future expansion #define U_EXTEND3 (1<<31) // another byte to follow, future expansion + +#define U_GROUP_ORIG (U_ORIGIN1 | U_ORIGIN2 | U_ORIGIN3 | \ + U_ANGLE2 | U_FRAME | U_REMOVE | U_MOREBITS) +#define U_GROUP_MOREBITS (U_ANGLE1 | U_ANGLE3 | U_MODEL | \ + U_COLORMAP | U_SKIN | U_EFFECTS | \ + U_SOLID | U_EXTEND1) +#define U_GROUP_EXTEND1 (U_ALPHA | U_SCALE | U_EFFECTS2 | \ + U_GLOWSIZE | U_GLOWCOLOR | U_COLORMOD | \ + U_EXTEND2) +#define U_GROUP_EXTEND2 (U_GLOWTRAIL | U_VIEWMODEL | U_FRAME2) +// I skip the UNUSED and EXTEND3 bits because although they exist in +// QSG2, they're not usable + +#define U_VERSION_ID ((U_GROUP_ORIG | U_GROUP_MOREBITS) & ~U_EXTEND1) +#define U_VERSION_QSG2 (U_VERSION_ID | U_EXTEND1 | U_GROUP_EXTEND1 | \ + U_GROUP_EFFECTS2) //============================================== // a sound with no channel is a local only sound diff --git a/qw/include/server.h b/qw/include/server.h index 26db73ac8..fcec31612 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -499,7 +499,7 @@ void SV_SendClientMessages (void); void SV_Multicast (vec3_t origin, int to); void SV_StartSound (struct edict_s *entity, int channel, const char *sample, - int volume, float attenuation); + float volume, float attenuation); void SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...) __attribute__((format(printf,3,4))); void SV_BroadcastPrintf (int level, const char *fmt, ...) __attribute__((format(printf,2,3))); void SV_BroadcastCommand (const char *fmt, ...) __attribute__((format(printf,1,2))); diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 9bbc02119..b2b5b1c0f 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -52,7 +52,7 @@ libasm_la_SOURCES= $(asm_src) noinst_LTLIBRARIES= libqfnet.la $(asm) common_sources= buildnum.c com.c game.c msg_ucmd.c pmove.c pmovetst.c \ - net_packetlog.c + net_packetlog.c net_svc.c common_ldflags= -export-dynamic diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 0b07f67ff..f61121743 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -265,8 +265,8 @@ CL_GetDemoMessage (void) (net_message->message->cursize); // Con_Printf("read: %ld bytes\n", net_message->message->cursize); if (net_message->message->cursize > MAX_MSGLEN + 8) //+8 for header - Host_EndGame ("Demo message > MAX_MSGLEN + 8: %d/%d", - net_message->message->cursize, MAX_MSGLEN + 8); + Host_Error ("Demo message > MAX_MSGLEN + 8: %d/%d", + net_message->message->cursize, MAX_MSGLEN + 8); r = Qread (cls.demofile, net_message->message->data, net_message->message->cursize); if (r != net_message->message->cursize) { diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 38957ac33..82eb29c91 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -43,6 +43,7 @@ static const char rcsid[] = #include "QF/render.h" #include "QF/skin.h" +#include "bothdefs.h" #include "cl_cam.h" #include "cl_ents.h" #include "cl_main.h" @@ -53,6 +54,7 @@ static const char rcsid[] = #include "d_iface.h" #include "host.h" #include "msg_ucmd.h" +#include "net_svc.h" #include "pmove.h" #include "r_cvar.h" #include "r_dynamic.h" @@ -69,6 +71,7 @@ entity_t cl_flag_ents[MAX_CLIENTS]; entity_t cl_player_ents[MAX_CLIENTS]; + void CL_ClearEnts () { @@ -124,221 +127,168 @@ CL_NewDlight (int key, vec3_t org, int effects) int bitcounts[32]; // / just for protocol profiling -/* - CL_ParseDelta - - Can go from either a baseline or a previous packet_entity -*/ void -CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) +CL_EntityState_Copy (entity_state_t *src, entity_state_t *dest, int bits) { - int i; - - // set everything to the state we are delta'ing from - *to = *from; - - to->number = bits & 511; - bits &= ~511; - - if (bits & U_MOREBITS) { // read in the low order bits - i = MSG_ReadByte (net_message); - bits |= i; - } - // count the bits for net profiling -// for (i=0 ; i<16 ; i++) -// if (bits&(1<flags = bits; - if (bits & U_MODEL) - to->modelindex = MSG_ReadByte (net_message); - + dest->modelindex = src->modelindex; if (bits & U_FRAME) - to->frame = MSG_ReadByte (net_message); - + dest->frame = (dest->frame & 0xFF00) | (src->frame & 0xFF); if (bits & U_COLORMAP) - to->colormap = MSG_ReadByte (net_message); - + dest->colormap = src->colormap; if (bits & U_SKIN) - to->skinnum = MSG_ReadByte (net_message); - + dest->skinnum = src->skinnum; if (bits & U_EFFECTS) - to->effects = MSG_ReadByte (net_message); + dest->effects = (dest->effects & 0xFF00) | (src->effects & 0xFF); if (bits & U_ORIGIN1) - to->origin[0] = MSG_ReadCoord (net_message); - + dest->origin[0] = src->origin[0]; if (bits & U_ANGLE1) - to->angles[0] = MSG_ReadAngle (net_message); - + dest->angles[0] = src->angles[0]; if (bits & U_ORIGIN2) - to->origin[1] = MSG_ReadCoord (net_message); - + dest->origin[1] = src->origin[1]; if (bits & U_ANGLE2) - to->angles[1] = MSG_ReadAngle (net_message); - + dest->angles[1] = src->angles[1]; if (bits & U_ORIGIN3) - to->origin[2] = MSG_ReadCoord (net_message); - + dest->origin[2] = src->origin[2]; if (bits & U_ANGLE3) - to->angles[2] = MSG_ReadAngle (net_message); + dest->angles[2] = src->angles[2]; - // LordHavoc: Endy neglected to mark this as being part of the QSG - // version 2 stuff... rearranged it and implemented missing effects -// Ender (QSG - Begin) if (bits & U_ALPHA) - to->alpha = MSG_ReadByte (net_message); + dest->alpha = src->alpha; if (bits & U_SCALE) - to->scale = MSG_ReadByte (net_message); + dest->scale = src->scale; if (bits & U_EFFECTS2) - to->effects = (to->effects & 0xFF) | (MSG_ReadByte (net_message) << 8); + dest->effects = (dest->effects & 0xFF) | (src->effects & 0xFF00); if (bits & U_GLOWSIZE) - to->glow_size = MSG_ReadByte (net_message); + dest->glow_size = src->glow_size; if (bits & U_GLOWCOLOR) - to->glow_color = MSG_ReadByte (net_message); + dest->glow_color = src->glow_color; if (bits & U_COLORMOD) - to->colormod = MSG_ReadByte (net_message); + dest->colormod = src->colormod; if (bits & U_FRAME2) - to->frame = (to->frame & 0xFF) | (MSG_ReadByte (net_message) << 8); -// Ender (QSG - End) + dest->frame = (dest->frame & 0xFF) | (src->frame & 0xFF00); if (bits & U_SOLID) { // FIXME } -/* - if ((!to->alpha) || (!to->colormod)) - Con_Printf("fa: %d, fc: %d, ta: %d, tc: %d\n", - from->alpha, from->colormod, to->alpha, to->colormod); -*/ -/* - if ((!ent->alpha) || (!ent->colormod[0]) || (!ent->colormod[1]) || - (!ent->colormod[2])) { - Con_Printf ("ea: %f, ec0: %f, ec1: %f ec2: %f, sa: %d, sc: %d\n", - ent->alpha, ent->colormod[0], ent->colormod[1], - ent->colormod[2], s1->alpha, s1->colormod); - } -*/ } void -FlushEntityPacket (void) +CL_ParsePacketEntities (void) { - entity_state_t olde, newe; - int word; + int index, packetnum; + packet_entities_t *newp; + net_svc_packetentities_t block; - Con_DPrintf ("FlushEntityPacket\n"); + packetnum = cls.netchan.incoming_sequence & UPDATE_MASK; + newp = &cl.frames[packetnum].packet_entities; + cl.frames[packetnum].invalid = false; - memset (&olde, 0, sizeof (olde)); + cl.validsequence = cls.netchan.incoming_sequence; - cl.validsequence = 0; // can't render a frame - cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].invalid = true; + newp->num_entities = 0; - // read it all, but ignore it - while (1) { - word = (unsigned short) MSG_ReadShort (net_message); - if (net_message->badread) { // something didn't parse right... - Host_EndGame ("msg_badread in packetentities"); + if (NET_SVC_PacketEntities_Parse (&block, net_message)) { + Host_NetError ("CL_ParsePacketEntities: Bad Read"); + return; + } + + for (index = 0; block.words[index]; index++) { + if (block.words[index] & U_REMOVE) { + Host_NetError ("CL_ParsePacketEntities: U_REMOVE on full " + "update\n"); + cl.validsequence = 0; // XXX + cl.frames[packetnum].invalid = true; return; } - if (!word) - break; // done + if (index >= MAX_PACKET_ENTITIES) { + Host_NetError ("CL_ParsePacketEntities: index %i >= " + "MAX_PACKET_ENTITIES", index); + return; + } - CL_ParseDelta (&olde, &newe, word); + newp->entities[index] = cl_baselines[block.words[index] & 511]; + CL_EntityState_Copy (&block.deltas[index], + &newp->entities[index], + block.deltas[index].flags); + newp->entities[index].number = block.deltas[index].number; + if (newp->entities[index].modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " + "MAX_MODELS", newp->entities[index].modelindex); + return; + } + continue; } + + newp->num_entities = index; } /* - CL_ParsePacketEntities + CL_ParseDeltaPacketEntities An svc_packetentities has just been parsed, deal with the rest of the data stream. */ void -CL_ParsePacketEntities (qboolean delta) +CL_ParseDeltaPacketEntities () { - byte from; - int oldindex, newindex, newnum, oldnum, oldpacket, newpacket, word; - packet_entities_t *oldp, *newp, dummy; - qboolean full; + int oldindex = 0, newindex = 0; + int wordindex = 0, deltaindex = 0; + int oldnum, newnum; + int oldpacket, newpacket; + packet_entities_t *oldp, *newp; + net_svc_deltapacketentities_t block; + + if (NET_SVC_DeltaPacketEntities_Parse (&block, net_message)) { + Host_NetError ("CL_ParseDeltaPacketEntities: Bad Read"); + return; + } newpacket = cls.netchan.incoming_sequence & UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; - if (delta) { - from = MSG_ReadByte (net_message); + oldpacket = cl.frames[newpacket].delta_sequence; - oldpacket = cl.frames[newpacket].delta_sequence; - - if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) - Con_DPrintf ("WARNING: from mismatch\n"); - } else - oldpacket = -1; - - full = false; - if (oldpacket != -1) { - if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) { - // we can't use this, it is too old - FlushEntityPacket (); - return; - } - cl.validsequence = cls.netchan.incoming_sequence; - oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities; - } else { // a full update that we can start delta compressing from now - oldp = &dummy; - dummy.num_entities = 0; - cl.validsequence = cls.netchan.incoming_sequence; - full = true; + if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) { + // we can't use this, it is too old + Con_DPrintf ("CL_ParseDeltaPacketEntities: old packet\n"); + cl.validsequence = 0; // can't render a frame + cl.frames[newpacket].invalid = true; + return; + } + if ((block.from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) { + Con_DPrintf ("CL_ParseDeltaPacketEntities: from mismatch\n"); + cl.validsequence = 0; + cl.frames[newpacket].invalid = true; + return; + } + if (oldpacket == -1) { + Host_NetError ("Cl_ParseDeltaPacketEntities: invalid " + "delta_sequence\n"); + return; } - oldindex = 0; - newindex = 0; + cl.validsequence = cls.netchan.incoming_sequence; + oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities; + newp->num_entities = 0; - while (1) { - word = (unsigned short) MSG_ReadShort (net_message); - if (net_message->badread) { // something didn't parse right... - Host_EndGame ("msg_badread in packetentities"); - return; - } - - if (!word) { // copy rest of ents from old packet - while (oldindex < oldp->num_entities) { -// Con_Printf ("copy %i\n", oldp->entities[oldindex].number); - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == " - "MAX_PACKET_ENTITIES"); - newp->entities[newindex] = oldp->entities[oldindex]; - newindex++; - oldindex++; - } - break; - } - newnum = word & 511; + for (; block.words[wordindex];) { + newnum = block.words[wordindex] & 511; oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; - while (newnum > oldnum) { - if (full) { - Con_Printf ("WARNING: oldcopy on full update"); - FlushEntityPacket (); + while (newnum > oldnum) { // copy one of the old entities + // over to the new packet unchanged +// Con_Printf ("copy %i\n", oldnum); + if (newindex >= MAX_PACKET_ENTITIES) { + Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= " + "MAX_PACKET_ENTITIES (1st)"); return; } -// Con_Printf ("copy %i\n", oldnum); - // copy one of the old entities over to the new packet unchanged - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == " - "MAX_PACKET_ENTITIES"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; @@ -348,44 +298,74 @@ CL_ParsePacketEntities (qboolean delta) if (newnum < oldnum) { // new from baseline // Con_Printf ("baseline %i\n", newnum); - if (word & U_REMOVE) { - if (full) { - cl.validsequence = 0; - Con_Printf ("WARNING: U_REMOVE on full update\n"); - FlushEntityPacket (); - return; - } + if (block.words[wordindex] & U_REMOVE) { + wordindex++; continue; } - if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == " - "MAX_PACKET_ENTITIES"); - CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], - word); + if (newindex >= MAX_PACKET_ENTITIES) { + Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= " + "MAX_PACKET_ENTITIES (2nd)"); + return; + } + newp->entities[newindex] = cl_baselines[newnum]; + CL_EntityState_Copy (&block.deltas[deltaindex], + &newp->entities[newindex], + block.deltas[deltaindex].flags); + newp->entities[newindex].number + = block.deltas[deltaindex].number; + if (newp->entities[newindex].modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " + "MAX_MODELS", + newp->entities[newindex].modelindex); + return; + } + wordindex++; + deltaindex++; newindex++; continue; } if (newnum == oldnum) { // delta from previous - if (full) { - cl.validsequence = 0; - Con_Printf ("WARNING: delta on full update"); - } - if (word & U_REMOVE) { // Clear the entity - entity_t *ent = &cl_packet_ents[newnum]; - memset (ent, 0, sizeof (entity_t)); +// Con_Printf ("delta %i\n", newnum); + if (block.words[wordindex] & U_REMOVE) { // Clear the entity + memset (&cl_packet_ents[newnum], 0, sizeof (entity_t)); + wordindex++; oldindex++; continue; } -// Con_Printf ("delta %i\n", newnum); - CL_ParseDelta (&oldp->entities[oldindex], - &newp->entities[newindex], word); + newp->entities[newindex] = oldp->entities[oldindex]; + CL_EntityState_Copy (&block.deltas[deltaindex], + &newp->entities[newindex], + block.deltas[deltaindex].flags); + newp->entities[newindex].number + = block.deltas[deltaindex].number; + if (newp->entities[newindex].modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParsePacketEntities: modelindex %i >= " + "MAX_MODELS", + newp->entities[newindex].modelindex); + return; + } + + wordindex++; + deltaindex++; newindex++; oldindex++; } } + while (oldindex < oldp->num_entities) { // copy rest of ents from old packet +// Con_Printf ("copy %i\n", oldp->entities[oldindex].number); + if (newindex >= MAX_PACKET_ENTITIES) { + Host_NetError ("CL_ParseDeltaPacketEntities: newindex >= " + "MAX_PACKET_ENTITIES (3rd)"); + return; + } + newp->entities[newindex] = oldp->entities[oldindex]; + newindex++; + oldindex++; + } + newp->num_entities = newindex; } @@ -543,7 +523,6 @@ typedef struct { entity_t ent; } projectile_t; -#define MAX_PROJECTILES 32 projectile_t cl_projectiles[MAX_PROJECTILES]; int cl_num_projectiles; @@ -561,27 +540,25 @@ CL_ClearProjectiles (void) void CL_ParseProjectiles (void) { - byte bits[6]; - int i, c, j; + int i; projectile_t *pr; + net_svc_nails_t block; - c = MSG_ReadByte (net_message); - for (i = 0; i < c; i++) { - for (j = 0; j < 6; j++) - bits[j] = MSG_ReadByte (net_message); + if (NET_SVC_Nails_Parse (&block, net_message)) { + Host_NetError ("CL_ParseProjectiles: Bad Read\n"); + return; + } + for (i = 0; i < block.numnails; i++) { if (cl_num_projectiles == MAX_PROJECTILES) - continue; + break; pr = &cl_projectiles[cl_num_projectiles]; cl_num_projectiles++; pr->modelindex = cl_spikeindex; - pr->ent.origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; - pr->ent.origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; - pr->ent.origin[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096; - pr->ent.angles[0] = 360 * (bits[4] >> 4) / 16; - pr->ent.angles[1] = 360 * bits[5] / 256; + VectorCopy (block.nails[i].origin, pr->ent.origin); + VectorCopy (block.nails[i].angles, pr->ent.angles); } } @@ -617,66 +594,57 @@ CL_LinkProjectiles (void) } } + void CL_ParsePlayerinfo (void) { - int flags, msec, num, i; player_state_t *state; + net_svc_playerinfo_t block; - num = MSG_ReadByte (net_message); - if (num > MAX_CLIENTS) -// Sys_Error ("CL_ParsePlayerinfo: bad num"); - Host_EndGame ("CL_ParsePlayerinfo: bad num"); + if (NET_SVC_Playerinfo_Parse (&block, net_message)) { + Host_NetError ("CL_ParsePlayerinfo: Bad Read\n"); + return; + } - state = &cl.frames[parsecountmod].playerstate[num]; + if (block.playernum >= MAX_CLIENTS) { + Host_NetError ("CL_ParsePlayerinfo: playernum %i >= MAX_CLIENTS", + block.playernum); + return; + } + if (block.modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParsePlayerinfo: modelindex %i >= MAX_MODELS", + block.modelindex); + return; + } - state->number = num; - flags = state->flags = MSG_ReadShort (net_message); + state = &cl.frames[parsecountmod].playerstate[block.playernum]; + + state->number = block.playernum; + state->flags = block.flags; state->messagenum = cl.parsecount; - state->origin[0] = MSG_ReadCoord (net_message); - state->origin[1] = MSG_ReadCoord (net_message); - state->origin[2] = MSG_ReadCoord (net_message); + VectorCopy (block.origin, state->origin); - state->frame = MSG_ReadByte (net_message); + state->frame = block.frame; // the other player's last move was likely some time // before the packet was sent out, so accurately track // the exact time it was valid at - if (flags & PF_MSEC) { - msec = MSG_ReadByte (net_message); - state->state_time = parsecounttime - msec * 0.001; - } else - state->state_time = parsecounttime; + state->state_time = parsecounttime - block.msec * 0.001; - if (flags & PF_COMMAND) - MSG_ReadDeltaUsercmd (&nullcmd, &state->command); + if (block.flags & PF_COMMAND) + memcpy (&state->command, &block.usercmd, sizeof (state->command)); - for (i = 0; i < 3; i++) { - if (flags & (PF_VELOCITY1 << i)) - state->velocity[i] = MSG_ReadShort (net_message); - else - state->velocity[i] = 0; - } - if (flags & PF_MODEL) - state->modelindex = MSG_ReadByte (net_message); + VectorCopy (block.velocity, state->velocity); + + if (block.flags & PF_MODEL) + state->modelindex = block.modelindex; else state->modelindex = cl_playerindex; - if (flags & PF_SKINNUM) - state->skinnum = MSG_ReadByte (net_message); - else - state->skinnum = 0; - - if (flags & PF_EFFECTS) - state->effects = MSG_ReadByte (net_message); - else - state->effects = 0; - - if (flags & PF_WEAPONFRAME) - state->weaponframe = MSG_ReadByte (net_message); - else - state->weaponframe = 0; + state->skinnum = block.skinnum; + state->effects = block.effects; + state->weaponframe = block.weaponframe; VectorCopy (state->command.angles, state->viewangles); } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 32d2835c0..3be93a59a 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1318,6 +1318,34 @@ Host_EndGame (const char *message, ...) longjmp (host_abort, 1); } +/* + Host_NetError + + Used for networking errors that disconnect, but don't exit the + client +*/ +void +Host_NetError (const char *message, ...) +{ + va_list argptr; + int old = 0; + + old = net_packetlog->int_val; + if (net_packetlog->int_val) + Cvar_Set (net_packetlog, "0"); + Log_Incoming_Packet (net_message->message->data, + net_message->message->cursize); + if (old) + Cvar_SetValue (net_packetlog, old); + + va_start (argptr, message); + Host_EndGame (message, argptr); + Con_Printf ("%s", "Please report this to " + "quake-devel@lists.sourceforge.net, including the " + "packet log printed out above\n"); + va_end (argptr); +} + /* Host_Error diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 7c35d945e..3a360cb0a 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -51,6 +51,7 @@ static const char rcsid[] = #include "QF/msg.h" #include "QF/screen.h" #include "QF/sound.h" +#include "QF/sys.h" #include "QF/teamplay.h" #include "QF/va.h" #include "QF/vfile.h" @@ -65,90 +66,12 @@ static const char rcsid[] = #include "client.h" #include "compat.h" #include "host.h" +#include "net_svc.h" #include "pmove.h" #include "protocol.h" #include "sbar.h" #include "view.h" -char *svc_strings[] = { - "svc_bad", - "svc_nop", - "svc_disconnect", - "svc_updatestat", - "svc_version", // [long] server version - "svc_setview", // [short] entity number - "svc_sound", // - "svc_time", // [float] server time - "svc_print", // [string] null terminated string - "svc_stufftext", // [string] stuffed into client's console - // buffer the string should be \n terminated - "svc_setangle", // [vec3] set view angle to this absolute value - - "svc_serverdata", // [long] version ... - "svc_lightstyle", // [byte] [string] - "svc_updatename", // [byte] [string] - "svc_updatefrags", // [byte] [short] - "svc_clientdata", // - "svc_stopsound", // - "svc_updatecolors", // [byte] [byte] - "svc_particle", // [vec3] - "svc_damage", // [byte] impact [byte] blood [vec3] from - - "svc_spawnstatic", - "OBSOLETE svc_spawnbinary", - "svc_spawnbaseline", - - "svc_temp_entity", // - "svc_setpause", - "svc_signonnum", - "svc_centerprint", - "svc_killedmonster", - "svc_foundsecret", - "svc_spawnstaticsound", - "svc_intermission", - "svc_finale", - - "svc_cdtrack", - "svc_sellscreen", - - "svc_smallkick", - "svc_bigkick", - - "svc_updateping", - "svc_updateentertime", - - "svc_updatestatlong", - "svc_muzzleflash", - "svc_updateuserinfo", - "svc_download", - "svc_playerinfo", - "svc_nails", - "svc_choke", - "svc_modellist", - "svc_soundlist", - "svc_packetentities", - "svc_deltapacketentities", - "svc_maxspeed", - "svc_entgravity", - - "svc_setinfo", - "svc_serverinfo", - "svc_updatepl", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL" -}; - int oldparsecountmod; int parsecountmod; double parsecounttime; @@ -401,19 +324,18 @@ void CL_ParseDownload (void) { byte name[1024]; - int size, percent, r; + int r; + net_svc_download_t download; - // read the data - size = MSG_ReadShort (net_message); - percent = MSG_ReadByte (net_message); - - if (cls.demoplayback) { - if (size > 0) - net_message->readcount += size; - return; // not in demo playback + if (NET_SVC_Download_Parse (&download, net_message)) { + Host_NetError ("CL_ParseDownload: Bad Read\n"); + return; } - if (size == -1) { + if (cls.demoplayback) + return; // not in demo playback + + if (download.size == -1) { Con_Printf ("File not found.\n"); if (cls.download) { Con_Printf ("cls.download shouldn't have been set\n"); @@ -424,14 +346,12 @@ CL_ParseDownload (void) return; } - if (size == -2) { - const char *newname = MSG_ReadString (net_message); - - if (strncmp (newname, cls.downloadname, strlen (cls.downloadname)) - || strstr (newname + strlen (cls.downloadname), "/")) { - Con_Printf - ("WARNING: server tried to give a strange new name: %s\n", - newname); + if (download.size == -2) { + // don't compare past the end of cls.downloadname due to gz support + if (strncmp (download.name, cls.downloadname, strlen (cls.downloadname)) + || strstr (download.name + strlen (cls.downloadname), "/")) { + Con_Printf ("WARNING: server tried to give a strange new " + "name: %s\n", download.name); CL_RequestNextDownload (); return; } @@ -439,10 +359,17 @@ CL_ParseDownload (void) Qclose (cls.download); unlink (cls.downloadname); } - strncpy (cls.downloadname, newname, sizeof (cls.downloadname)); + strncpy (cls.downloadname, download.name, + sizeof (cls.downloadname) - 1); Con_Printf ("downloading to %s\n", cls.downloadname); return; } + + if (download.size <= 0) { + Host_NetError ("Bad download block, size %d", download.size); + return; + } + // open the file if not opened yet if (!cls.download) { if (strncmp (cls.downloadtempname, "skins/", 6)) @@ -456,31 +383,28 @@ CL_ParseDownload (void) cls.download = Qopen (name, "wb"); if (!cls.download) { - net_message->readcount += size; Con_Printf ("Failed to open %s\n", cls.downloadtempname); CL_RequestNextDownload (); return; } } - Qwrite (cls.download, net_message->message->data + net_message->readcount, - size); - net_message->readcount += size; + Qwrite (cls.download, download.data, download.size); - if (percent != 100) { + if (download.percent != 100) { // change display routines by zoid // request next block #if 0 Con_Printf ("."); - if (10 * (percent / 10) != cls.downloadpercent) { - cls.downloadpercent = 10 * (percent / 10); + if (10 * (download.percent / 10) != cls.downloadpercent) { + cls.downloadpercent = 10 * (download.percent / 10); Con_Printf ("%i%%", cls.downloadpercent); } #endif - if (percent != cls.downloadpercent) + if (download.percent != cls.downloadpercent) VID_SetCaption (va ("Downloading %s %d%%", cls.downloadname, - percent)); - cls.downloadpercent = percent; + download.percent)); + cls.downloadpercent = download.percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "nextdl"); @@ -574,6 +498,8 @@ CL_StartUpload (byte * data, int size) Con_DPrintf ("Upload starting of %d...\n", size); upload_data = malloc (size); + if (!upload_data) + Sys_Error ("CL_StartUpload: Memory Allocation Failure\n"); memcpy (upload_data, data, size); upload_size = size; upload_pos = 0; @@ -597,6 +523,40 @@ CL_StopUpload (void) upload_data = NULL; } +void +CL_ParsePrint (void) +{ + const char *string; + char tmpstring[2048]; + net_svc_print_t print; + + if (NET_SVC_Print_Parse (&print, net_message)) { + Host_NetError ("CL_ParsePrint: Bad Read\n"); + return; + } + string = print.message; + + if (print.level == PRINT_CHAT) { + // TODO: cl_nofake 2 -- accept fake messages from + // teammates + + if (cl_nofake->int_val) { + char *c; + strncpy (tmpstring, string, sizeof (tmpstring)); + tmpstring[sizeof (tmpstring) - 1] = 0; + for (c = tmpstring; *c; c++) + if (*c == '\r') + *c = '#'; + string = tmpstring; + } + con_ormask = 128; + S_LocalSound ("misc/talk.wav"); + Team_ParseChat(string); + } + Con_Printf ("%s", string); + con_ormask = 0; +} + /* SERVER CONNECTING MESSAGES */ void Draw_ClearCache (void); @@ -606,40 +566,44 @@ void CL_ParseServerData (void) { char fn[MAX_OSPATH]; - const char *str; int protover; qboolean cflag = false; - - extern char gamedirfile[MAX_OSPATH]; + net_svc_serverdata_t serverdata; Con_DPrintf ("Serverdata packet received.\n"); + if (NET_SVC_ServerData_Parse (&serverdata, net_message)) { + Host_NetError ("CL_ParseServerData: Bad Read\n"); + return; + } + + // make sure any stuffed commands are done + Cbuf_Execute (); + // wipe the client_state_t struct CL_ClearState (); // parse protocol version number // allow 2.2 and 2.29 demos to play - protover = MSG_ReadLong (net_message); + protover = serverdata.protocolversion; if (protover != PROTOCOL_VERSION && !(cls.demoplayback && (protover <= 26 && protover >= 28))) - Host_EndGame ("Server returned version %i, not %i\nYou probably " - "need to upgrade.\nCheck http://www.quakeworld.net/", - protover, PROTOCOL_VERSION); + Host_NetError ("Server returned version %i, not %i\nYou probably " + "need to upgrade.\nCheck http://www.quakeworld.net/", + protover, PROTOCOL_VERSION); - cl.servercount = MSG_ReadLong (net_message); + cl.servercount = serverdata.servercount; // game directory - str = MSG_ReadString (net_message); - - if (!strequal (gamedirfile, str)) { + if (!strequal (gamedirfile, serverdata.gamedir)) { // save current config Host_WriteConfiguration (); cflag = true; Draw_ClearCache (); } - COM_Gamedir (str); + COM_Gamedir (serverdata.gamedir); // ZOID--run the autoexec.cfg in the gamedir // if it exists @@ -655,11 +619,14 @@ CL_ParseServerData (void) snprintf (fn, sizeof (fn), "cmd_warncmd %d\n", cmd_warncmd_val); Cbuf_AddText (fn); } - // parse player slot, high bit means spectator - cl.playernum = MSG_ReadByte (net_message); - if (cl.playernum & 128) { - cl.spectator = true; - cl.playernum &= ~128; + + // parse player slot + cl.playernum = serverdata.playernum; + cl.spectator = serverdata.spectator; + if (cl.playernum >= MAX_CLIENTS) { + Host_NetError ("CL_ParseServerData: playernum %d >= MAX_CLIENTS", + cl.playernum); + return; } // FIXME: evil hack so NQ and QW can share sound code @@ -667,25 +634,15 @@ CL_ParseServerData (void) viewentity = cl.playernum + 1; // get the full level name - str = MSG_ReadString (net_message); - strncpy (cl.levelname, str, sizeof (cl.levelname) - 1); + strncpy (cl.levelname, serverdata.levelname, sizeof (cl.levelname) - 1); // get the movevars - movevars.gravity = MSG_ReadFloat (net_message); - movevars.stopspeed = MSG_ReadFloat (net_message); - movevars.maxspeed = MSG_ReadFloat (net_message); - movevars.spectatormaxspeed = MSG_ReadFloat (net_message); - movevars.accelerate = MSG_ReadFloat (net_message); - movevars.airaccelerate = MSG_ReadFloat (net_message); - movevars.wateraccelerate = MSG_ReadFloat (net_message); - movevars.friction = MSG_ReadFloat (net_message); - movevars.waterfriction = MSG_ReadFloat (net_message); - movevars.entgravity = MSG_ReadFloat (net_message); + memcpy (&movevars, &serverdata.movevars, sizeof (movevars)); // seperate the printfs so the server message can have a color Con_Printf ("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" "\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); - Con_Printf ("%c%s\n", 2, str); + Con_Printf ("%c%s\n", 2, serverdata.levelname); // ask for the sound list next memset (cl.sound_name, 0, sizeof (cl.sound_name)); @@ -697,6 +654,9 @@ CL_ParseServerData (void) CL_SetState (ca_onserver); CL_ClearBaselines (); + + // leave full screen intermission + vid.recalc_refdef = true; } // LordHavoc: BIG BUG-FIX! Clear baselines each time it connects... @@ -719,29 +679,32 @@ void CL_ParseSoundlist (void) { const char *str; - int numsounds, n; + int numsounds, i; + net_svc_soundlist_t soundlist; // precache sounds -// memset (cl.sound_precache, 0, sizeof(cl.sound_precache)); + if (NET_SVC_Soundlist_Parse (&soundlist, net_message)) { + Host_NetError ("CL_ParseSoundlist: Bad Read\n"); + return; + } - numsounds = MSG_ReadByte (net_message); - - for (;;) { - str = MSG_ReadString (net_message); + for (i = 0, numsounds = soundlist.startsound;; i++) { + str = soundlist.sounds[i]; if (!str[0]) break; numsounds++; - if (numsounds == MAX_SOUNDS) - Host_EndGame ("Server sent too many sound_precache"); + if (numsounds >= MAX_SOUNDS) { + Host_NetError ("CL_ParseSoundlist: too many sounds"); + return; + } strcpy (cl.sound_name[numsounds], str); } - n = MSG_ReadByte (net_message); - - if (n) { + if (soundlist.nextsound) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (soundlist_name, cl.servercount, n)); + va (soundlist_name, cl.servercount, + soundlist.nextsound)); return; } @@ -753,44 +716,50 @@ CL_ParseSoundlist (void) void CL_ParseModellist (void) { - int nummodels, n; + int nummodels, i; const char *str; + net_svc_modellist_t modellist; // precache models and note certain default indexes - nummodels = MSG_ReadByte (net_message); + if (NET_SVC_Modellist_Parse (&modellist, net_message)) { + Host_NetError ("CL_ParseModellist: Bad Read\n"); + return; + } - for (;;) { - str = MSG_ReadString (net_message); + for (i = 0, nummodels = modellist.startmodel;; i++) { + str = modellist.models[i]; if (!str[0]) break; nummodels++; - if (nummodels == MAX_MODELS) - Host_EndGame ("Server sent too many model_precache"); - strcpy (cl.model_name[nummodels], str); + if (nummodels >= MAX_MODELS) { + Host_NetError ("CL_ParseModellist: too many models"); + return; + } + strncpy (cl.model_name[nummodels], str, MAX_QPATH - 1); + cl.model_name[nummodels][MAX_QPATH - 1] = '\0'; - if (!strcmp (cl.model_name[nummodels], "progs/spike.mdl")) + if (!strcmp (str, "progs/spike.mdl")) cl_spikeindex = nummodels; - else if (!strcmp (cl.model_name[nummodels], "progs/player.mdl")) + else if (!strcmp (str, "progs/player.mdl")) cl_playerindex = nummodels; - else if (!strcmp (cl.model_name[nummodels], "progs/flag.mdl")) + else if (!strcmp (str, "progs/flag.mdl")) cl_flagindex = nummodels; // for deadbodyfilter & gibfilter - else if (!strcmp (cl.model_name[nummodels], "progs/h_player.mdl")) + else if (!strcmp (str, "progs/h_player.mdl")) cl_h_playerindex = nummodels; - else if (!strcmp (cl.model_name[nummodels], "progs/gib1.mdl")) + else if (!strcmp (str, "progs/gib1.mdl")) cl_gib1index = nummodels; - else if (!strcmp (cl.model_name[nummodels], "progs/gib2.mdl")) + else if (!strcmp (str, "progs/gib2.mdl")) cl_gib2index = nummodels; - else if (!strcmp (cl.model_name[nummodels], "progs/gib3.mdl")) + else if (!strcmp (str, "progs/gib3.mdl")) cl_gib3index = nummodels; } - n = MSG_ReadByte (net_message); - - if (n) { + if (modellist.nextmodel) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (modellist_name, cl.servercount, n)); + va (modellist_name, cl.servercount, + modellist.nextmodel)); return; } @@ -800,18 +769,212 @@ CL_ParseModellist (void) } void -CL_ParseBaseline (entity_state_t *es) +CL_ParseNOP (void) { - int i; + net_svc_nop_t block; - es->modelindex = MSG_ReadByte (net_message); - es->frame = MSG_ReadByte (net_message); - es->colormap = MSG_ReadByte (net_message); - es->skinnum = MSG_ReadByte (net_message); - for (i = 0; i < 3; i++) { - es->origin[i] = MSG_ReadCoord (net_message); - es->angles[i] = MSG_ReadAngle (net_message); + if (NET_SVC_NOP_Parse (&block, net_message)) { + Host_NetError ("CL_ParseNOP: Bad Read\n"); + return; } +} + +void +CL_ParseDisconnect (void) +{ + net_svc_disconnect_t block; + + if (NET_SVC_Disconnect_Parse (&block, net_message)) { + Host_NetError ("CL_ParseDisconnect: Bad Read\n"); + return; + } + + if (cls.state == ca_connected) + Host_EndGame ("Server disconnected\n" + "Server version may not be compatible"); + else + Host_EndGame ("Server disconnected"); +} + +void +CL_ParseCenterprint (void) +{ + net_svc_centerprint_t block; + + if (NET_SVC_Centerprint_Parse (&block, net_message)) { + Host_NetError ("CL_ParseCenterprint: Bad Read\n"); + return; + } + + SCR_CenterPrint (block.message); +} + +void +CL_ParseStufftext (void) +{ + net_svc_stufftext_t block; + + if (NET_SVC_Stufftext_Parse (&block, net_message)) { + Host_NetError ("CL_ParseStufftext: Bad Read\n"); + return; + } + + Con_DPrintf ("stufftext: %s\n", block.commands); + Cbuf_AddText (block.commands); +} + +void +CL_ParseSetAngle (void) +{ + net_svc_setangle_t block; + + if (NET_SVC_SetAngle_Parse (&block, net_message)) { + Host_NetError ("CL_ParseSetAngle: Bad Read\n"); + return; + } + + VectorCopy (block.angles, cl.viewangles); +} + +void +CL_ParseLightStyle (void) +{ + lightstyle_t *style; + net_svc_lightstyle_t block; + + if (NET_SVC_LightStyle_Parse (&block, net_message)) { + Host_NetError ("CL_ParseLightStyle: Bad Read\n"); + return; + } + + if (block.stylenum >= MAX_LIGHTSTYLES) { + Host_NetError ("svc_lightstyle > MAX_LIGHTSTYLES"); + return; + } + style = &r_lightstyle[block.stylenum]; + + strncpy (style->map, block.map, sizeof (style->map) - 1); + style->map[sizeof (style->map) - 1] = 0; + style->length = strlen (style->map); +} + +void +CL_ParseStopSound (void) +{ + net_svc_stopsound_t block; + + if (NET_SVC_StopSound_Parse (&block, net_message)) { + Host_NetError ("CL_ParseStopSound: Bad Read\n"); + return; + } + + S_StopSound (block.entity, block.channel); +} + +void +CL_ParseUpdateFrags (void) +{ + net_svc_updatefrags_t block; + + if (NET_SVC_UpdateFrags_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdateFrags: Bad Read\n"); + return; + } + + Sbar_Changed (); + if (block.player >= MAX_CLIENTS) { + Host_NetError ("CL_ParseServerMessage: svc_updatefrags > " + "MAX_SCOREBOARD"); + return; + } + cl.players[block.player].frags = block.frags; +} + +void +CL_ParseUpdatePing (void) +{ + net_svc_updateping_t block; + + if (NET_SVC_UpdatePing_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdatePing: Bad Read\n"); + return; + } + + if (block.player >= MAX_CLIENTS) { + Host_NetError ("CL_ParseServerMessage: svc_updateping > " + "MAX_SCOREBOARD"); + return; + } + cl.players[block.player].ping = block.ping; +} + +void +CL_ParseUpdatePL (void) +{ + net_svc_updatepl_t block; + + if (NET_SVC_UpdatePL_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdatePL: Bad Read\n"); + return; + } + + if (block.player >= MAX_CLIENTS) { + Host_NetError ("CL_ParseServerMessage: svc_updatepl > " + "MAX_SCOREBOARD"); + return; + } + cl.players[block.player].pl = block.packetloss; +} + +void +CL_ParseUpdateEnterTime (void) +{ + net_svc_updateentertime_t block; + + if (NET_SVC_UpdateEnterTime_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdateEnterTime: Bad Read\n"); + return; + } + + if (block.player >= MAX_CLIENTS) { + Host_NetError ("CL_ParseServerMessage: svc_updateentertime " + "> MAX_SCOREBOARD"); + return; + } + cl.players[block.player].entertime = realtime - block.secondsago; +} + +void +CL_ParseSpawnBaseline (void) +{ + entity_state_t *es; + net_svc_spawnbaseline_t block; + + if (NET_SVC_SpawnBaseline_Parse (&block, net_message)) { + Host_NetError ("CL_ParseSpawnBaseline: Bad Read\n"); + return; + } + + if (block.num >= MAX_EDICTS) { + Host_NetError ("CL_ParseSpawnBaseline: num %i >= MAX_EDICTS", + block.num); + return; + } + if (block.modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParseSpawnBaseline: modelindex %i >= MAX_MODELS", + block.modelindex); + return; + } + + es = &cl_baselines[block.num]; + + es->modelindex = block.modelindex; + es->frame = block.frame; + es->colormap = block.colormap; + es->skinnum = block.skinnum; + VectorCopy (block.origin, es->origin); + VectorCopy (block.angles, es->angles); + // LordHavoc: set up the baseline to account for new effects (alpha, // colormod, etc) es->alpha = 255; @@ -831,22 +994,33 @@ void CL_ParseStatic (void) { entity_t *ent; - entity_state_t es; + net_svc_spawnstatic_t block; - CL_ParseBaseline (&es); + if (NET_SVC_SpawnStatic_Parse (&block, net_message)) { + Host_NetError ("CL_ParseStatic: Bad Read\n"); + return; + } - if (cl.num_statics >= MAX_STATIC_ENTITIES) - Host_EndGame ("Too many static entities"); + if (block.modelindex >= MAX_MODELS) { + Host_NetError ("CL_ParseStatic: modelindex %i >= MAX_MODELS", + block.modelindex); + return; + } + + if (cl.num_statics >= MAX_STATIC_ENTITIES) { + Host_NetError ("Too many static entities"); + return; + } ent = &cl_static_entities[cl.num_statics++]; CL_Init_Entity (ent); // copy it to the current state - ent->model = cl.model_precache[es.modelindex]; - ent->frame = es.frame; - ent->skinnum = es.skinnum; + ent->model = cl.model_precache[block.modelindex]; + ent->frame = block.frame; + ent->skinnum = block.skinnum; - VectorCopy (es.origin, ent->origin); - VectorCopy (es.angles, ent->angles); + VectorCopy (block.origin, ent->origin); + VectorCopy (block.angles, ent->angles); R_AddEfrags (ent); } @@ -854,52 +1028,42 @@ CL_ParseStatic (void) void CL_ParseStaticSound (void) { - int sound_num, vol, atten, i; - vec3_t org; + net_svc_spawnstaticsound_t block; - for (i = 0; i < 3; i++) - org[i] = MSG_ReadCoord (net_message); - sound_num = MSG_ReadByte (net_message); - vol = MSG_ReadByte (net_message); - atten = MSG_ReadByte (net_message); + if (NET_SVC_SpawnStaticSound_Parse (&block, net_message)) { + Host_NetError ("CL_ParseStaticSound: Bad Read\n"); + return; + } - S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); + S_StaticSound (cl.sound_precache[block.sound_num], block.position, + block.volume, block.attenuation); } /* ACTION MESSAGES */ void -CL_ParseStartSoundPacket (void) +CL_ParseSound (void) { - float attenuation; - int channel, ent, sound_num, volume, i; - vec3_t pos; + net_svc_sound_t sound; - channel = MSG_ReadShort (net_message); + if (NET_SVC_Sound_Parse (&sound, net_message)) { + Host_NetError ("CL_ParseSound: Bad Read\n"); + return; + } - if (channel & SND_VOLUME) - volume = MSG_ReadByte (net_message); - else - volume = DEFAULT_SOUND_PACKET_VOLUME; + if (sound.entity >= MAX_EDICTS) { + Host_NetError ("CL_ParseSound: ent = %i", sound.entity); + return; + } + if (sound.sound_num >= MAX_SOUNDS) { + Host_NetError ("CL_ParseSound: sound_num = %i", + sound.sound_num); + return; + } - if (channel & SND_ATTENUATION) - attenuation = MSG_ReadByte (net_message) / 64.0; - else - attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; - - sound_num = MSG_ReadByte (net_message); - - for (i = 0; i < 3; i++) - pos[i] = MSG_ReadCoord (net_message); - - ent = (channel >> 3) & 1023; - channel &= 7; - - if (ent > MAX_EDICTS) - Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); - - S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, - volume / 255.0, attenuation); + S_StartSound (sound.entity, sound.channel, + cl.sound_precache[sound.sound_num], sound.position, + sound.volume, sound.attenuation); } /* @@ -975,74 +1139,80 @@ CL_ProcessUserInfo (int slot, player_info_t *player) } void -CL_UpdateUserinfo (void) +CL_ParseUpdateUserInfo (void) { - int slot; player_info_t *player; + net_svc_updateuserinfo_t updateuserinfo; - slot = MSG_ReadByte (net_message); - if (slot >= MAX_CLIENTS) - Host_EndGame - ("CL_ParseServerMessage: svc_updateuserinfo > MAX_SCOREBOARD"); + if (NET_SVC_UpdateUserInfo_Parse (&updateuserinfo, net_message)) { + Host_NetError ("CL_ParseUpdateUserInfo: Bad Read\n"); + return; + } - player = &cl.players[slot]; - player->userid = MSG_ReadLong (net_message); + if (updateuserinfo.slot >= MAX_CLIENTS) { + Host_NetError ("CL_ParseUpdateUserInfo: slot %i >= MAX_CLIENTS", + updateuserinfo.slot); + return; + } + + player = &cl.players[updateuserinfo.slot]; + player->userid = updateuserinfo.userid; if (player->userinfo) Info_Destroy (player->userinfo); - player->userinfo = Info_ParseString (MSG_ReadString (net_message), + player->userinfo = Info_ParseString (updateuserinfo.userinfo, MAX_INFO_STRING); - CL_ProcessUserInfo (slot, player); + CL_ProcessUserInfo (updateuserinfo.slot, player); } void -CL_SetInfo (void) +CL_ParseSetInfo (void) { - char key[MAX_MSGLEN], value[MAX_MSGLEN]; - int slot; - int flags; - player_info_t *player; + int flags; + player_info_t *player; + net_svc_setinfo_t setinfo; - slot = MSG_ReadByte (net_message); - if (slot >= MAX_CLIENTS) - Host_EndGame ("CL_ParseServerMessage: svc_setinfo > MAX_SCOREBOARD"); + if (NET_SVC_SetInfo_Parse (&setinfo, net_message)) { + Host_NetError ("CL_ParseSetInfo: Bad Read\n"); + return; + } - player = &cl.players[slot]; - - strncpy (key, MSG_ReadString (net_message), sizeof (key) - 1); - key[sizeof (key) - 1] = 0; - strncpy (value, MSG_ReadString (net_message), sizeof (value) - 1); - key[sizeof (value) - 1] = 0; - - Con_DPrintf ("SETINFO %s: %s=%s\n", player->name, key, value); + if (setinfo.slot >= MAX_CLIENTS) { + Host_NetError ("CL_ParseSetInfo: slot %i >= MAX_CLIENTS", setinfo.slot); + return; + } + player = &cl.players[setinfo.slot]; if (!player->userinfo) player->userinfo = Info_ParseString ("", MAX_INFO_STRING); - flags = !strequal (key, "name"); - flags |= strequal (key, "team") << 1; - Info_SetValueForKey (player->userinfo, key, value, flags); + Con_DPrintf ("SETINFO %s: %s=%s\n", player->name, setinfo.key, + setinfo.value); - CL_ProcessUserInfo (slot, player); + flags = !strequal (setinfo.key, "name"); + flags |= strequal (setinfo.key, "team") << 1; + Info_SetValueForKey (player->userinfo, setinfo.key, setinfo.value, flags); + + CL_ProcessUserInfo (setinfo.slot, player); } void -CL_ServerInfo (void) +CL_ParseServerInfo (void) { - char key[MAX_MSGLEN], value[MAX_MSGLEN]; + net_svc_serverinfo_t block; - strncpy (key, MSG_ReadString (net_message), sizeof (key) - 1); - key[sizeof (key) - 1] = 0; - strncpy (value, MSG_ReadString (net_message), sizeof (value) - 1); - key[sizeof (value) - 1] = 0; + if (NET_SVC_ServerInfo_Parse (&block, net_message)) { + Host_NetError ("CL_ParseServerInfo: Bad Read\n"); + return; + } - Con_DPrintf ("SERVERINFO: %s=%s\n", key, value); + Con_DPrintf ("SERVERINFO: %s=%s\n", block.key, block.value); - Info_SetValueForKey (cl.serverinfo, key, value, 0); - if (strequal (key, "chase")) { - cl.chase = atoi (value); - } else if (strequal (key, "watervis")) { - cl.watervis = atoi (value); + Info_SetValueForKey (cl.serverinfo, block.key, block.value, 0); + if (strequal (block.key, "chase")) { + cl.chase = atoi (block.value); + } else if (strequal (block.key, "watervis")) { + cl.watervis = atoi (block.value); } } @@ -1053,7 +1223,7 @@ CL_SetStat (int stat, int value) if (stat < 0 || stat >= MAX_CL_STATS) // Sys_Error ("CL_SetStat: %i is invalid", stat); - Host_EndGame ("CL_SetStat: %i is invalid", stat); + Host_NetError ("CL_SetStat: %i is invalid", stat); Sbar_Changed (); @@ -1074,16 +1244,164 @@ CL_SetStat (int stat, int value) } void -CL_MuzzleFlash (void) +CL_ParseKilledMonster (void) +{ + net_svc_killedmonster_t block; + + if (NET_SVC_KilledMonster_Parse (&block, net_message)) { + Host_NetError ("CL_ParseKilledMonster: Bad Read\n"); + return; + } + + cl.stats[STAT_MONSTERS]++; +} + +void +CL_ParseFoundSecret (void) +{ + net_svc_foundsecret_t block; + + if (NET_SVC_FoundSecret_Parse (&block, net_message)) { + Host_NetError ("CL_ParseFoundSecret: Bad Read\n"); + return; + } + + cl.stats[STAT_SECRETS]++; +} + +void +CL_ParseUpdateStat (void) +{ + net_svc_updatestat_t block; + + if (NET_SVC_UpdateStat_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdateStat: Bad Read\n"); + return; + } + + CL_SetStat (block.stat, block.value); +} + +void +CL_ParseUpdateStatLong (void) +{ + net_svc_updatestatlong_t block; + + if (NET_SVC_UpdateStatLong_Parse (&block, net_message)) { + Host_NetError ("CL_ParseUpdateStatLong: Bad Read\n"); + return; + } + + CL_SetStat (block.stat, block.value); +} + +void +CL_ParseCDTrack (void) +{ + net_svc_cdtrack_t block; + + if (NET_SVC_CDTrack_Parse (&block, net_message)) { + Host_NetError ("CL_ParseCDTrack: Bad Read\n"); + return; + } + + cl.cdtrack = block.cdtrack; + CDAudio_Play (cl.cdtrack, true); +} + +void +CL_ParseIntermission (void) +{ + net_svc_intermission_t block; + + if (NET_SVC_Intermission_Parse (&block, net_message)) { + Host_NetError ("CL_ParseIntermission: Bad Read\n"); + return; + } + + cl.intermission = 1; + cl.completed_time = realtime; + vid.recalc_refdef = true; // go to full screen + VectorCopy (block.origin, cl.simorg); + VectorCopy (block.angles, cl.simangles); + VectorCopy (vec3_origin, cl.simvel); + + Con_DPrintf ("Intermission origin: %f %f %f\nIntermission angles: " + "%f %f %f\n", cl.simorg[0], cl.simorg[1], cl.simorg[2], + cl.simangles[0], cl.simangles[1], cl.simangles[2]); +} + +void +CL_ParseFinale (void) +{ + net_svc_finale_t block; + + if (NET_SVC_Finale_Parse (&block, net_message)) { + Host_NetError ("CL_ParseFinale: Bad Read\n"); + return; + } + + cl.intermission = 2; + cl.completed_time = realtime; + vid.recalc_refdef = true; // go to full screen + SCR_CenterPrint (block.message); +} + +void +CL_ParseSellScreen (void) +{ + net_svc_sellscreen_t block; + + if (NET_SVC_SellScreen_Parse (&block, net_message)) { + Host_NetError ("CL_ParseSellScreen: Bad Read\n"); + return; + } + + Cmd_ExecuteString ("help", src_command); +} + +void +CL_ParseSmallKick (void) +{ + net_svc_smallkick_t block; + + if (NET_SVC_SmallKick_Parse (&block, net_message)) { + Host_NetError ("CL_ParseSmallKick: Bad Read\n"); + return; + } + + cl.punchangle = -2; +} + +void +CL_ParseBigKick (void) +{ + net_svc_bigkick_t block; + + if (NET_SVC_BigKick_Parse (&block, net_message)) { + Host_NetError ("CL_ParseBigKick: Bad Read\n"); + return; + } + + cl.punchangle = -4; +} + +void +CL_ParseMuzzleFlash (void) { dlight_t *dl; int i; player_state_t *pl; vec3_t fv, rv, uv; + net_svc_muzzleflash_t block; - i = MSG_ReadShort (net_message); + if (NET_SVC_MuzzleFlash_Parse (&block, net_message)) { + Host_NetError ("CL_ParseMuzzleFlash: Bad Read\n"); + return; + } - if ((unsigned int) (i - 1) >= MAX_CLIENTS) + i = block.player; + if (i < 1 || i > MAX_CLIENTS) return; pl = &cl.frames[parsecountmod].playerstate[i - 1]; @@ -1105,15 +1423,71 @@ CL_MuzzleFlash (void) dl->color[2] = 0.05; } -#define SHOWNET(x) if (cl_shownet->int_val == 2) Con_Printf ("%3i:%s\n", net_message->readcount-1, x); +void +CL_ParseChokeCount (void) +{ + int j; + net_svc_chokecount_t block; + + if (NET_SVC_ChokeCount_Parse (&block, net_message)) { + Host_NetError ("CL_ParseChokeCount: Bad Read\n"); + return; + } + + for (j = 0; j < block.count; j++) + cl.frames[(cls.netchan.incoming_acknowledged - 1 - j) & + UPDATE_MASK].receivedtime = -2; +} + +void +CL_ParseMaxSpeed (void) +{ + net_svc_maxspeed_t block; + + if (NET_SVC_MaxSpeed_Parse (&block, net_message)) { + Host_NetError ("CL_ParseEntGravity: Bad Read\n"); + return; + } + + movevars.maxspeed = block.maxspeed; +} + +void +CL_ParseEntGravity (void) +{ + net_svc_entgravity_t block; + + if (NET_SVC_EntGravity_Parse (&block, net_message)) { + Host_NetError ("CL_ParseEntGravity: Bad Read\n"); + return; + } + + movevars.entgravity = block.gravity; +} + +void +CL_ParseSetPause (void) +{ + net_svc_setpause_t block; + + if (NET_SVC_SetPause_Parse (&block, net_message)) { + Host_NetError ("CL_ParseSetPause: Bad Read\n"); + return; + } + + cl.paused = block.paused; + if (cl.paused) + CDAudio_Pause (); + else + CDAudio_Resume (); +} int received_framecount; void CL_ParseServerMessage (void) { - const char *s; - int cmd, i, j; + int cmd; received_framecount = host_framecount; cl.last_servermessage = realtime; @@ -1129,290 +1503,78 @@ CL_ParseServerMessage (void) // parse the message while (1) { + if (cls.state == ca_disconnected) + break; // something called Host_NetError + if (net_message->badread) { - Host_EndGame ("CL_ParseServerMessage: Bad server message"); + Host_NetError ("CL_ParseServerMessage: Bad server message"); break; } cmd = MSG_ReadByte (net_message); if (cmd == -1) { - net_message->readcount++; // so the EOM showner has the right - // value - SHOWNET ("END OF MESSAGE"); + if (cl_shownet->int_val == 2) + Con_Printf ("%3i:%s\n", net_message->readcount, + "END OF MESSAGE"); break; } - SHOWNET (svc_strings[cmd]); + if (cl_shownet->int_val == 2) + Con_Printf ("%3i:%s\n", net_message->readcount - 1, + NET_SVC_GetString (cmd)); // other commands switch (cmd) { default: - Host_EndGame - ("CL_ParseServerMessage: Illegible server message"); - break; - - case svc_nop: -// Con_Printf ("svc_nop\n"); - break; - - case svc_disconnect: - if (cls.state == ca_connected) - Host_EndGame ("Server disconnected\n" - "Server version may not be compatible"); - else - Host_EndGame ("Server disconnected"); - break; - - case svc_print: { - char p[2048]; - i = MSG_ReadByte (net_message); - s = MSG_ReadString (net_message); - if (i == PRINT_CHAT) { - // TODO: cl_nofake 2 -- accept fake messages from teammates - - if (cl_nofake->int_val) { - char *c; - strncpy (p, s, sizeof (p)); - p[sizeof (p) - 1] = 0; - for (c = p; *c; c++) { - if (*c == '\r') - *c = '#'; - } - s = p; - } - con_ormask = 128; - S_LocalSound ("misc/talk.wav"); - Team_ParseChat(s); - } - Con_Printf ("%s", s); - con_ormask = 0; - break; - } - case svc_centerprint: - SCR_CenterPrint (MSG_ReadString (net_message)); - break; - - case svc_stufftext: - s = MSG_ReadString (net_message); - Con_DPrintf ("stufftext: %s\n", s); - Cbuf_AddText (s); - break; - - case svc_damage: - V_ParseDamage (); - break; - - case svc_serverdata: - Cbuf_Execute (); // make sure any stuffed commands are - // done - CL_ParseServerData (); - vid.recalc_refdef = true; // leave full screen intermission - break; - - case svc_setangle: - for (i = 0; i < 3; i++) - cl.viewangles[i] = MSG_ReadAngle (net_message); -// cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0; - break; - - case svc_lightstyle: - i = MSG_ReadByte (net_message); - if (i >= MAX_LIGHTSTYLES) -// Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); - Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); - strcpy (r_lightstyle[i].map, MSG_ReadString (net_message)); - r_lightstyle[i].length = strlen (r_lightstyle[i].map); - break; - - case svc_sound: - CL_ParseStartSoundPacket (); - break; - - case svc_stopsound: - i = MSG_ReadShort (net_message); - S_StopSound (i >> 3, i & 7); - break; - - case svc_updatefrags: - Sbar_Changed (); - i = MSG_ReadByte (net_message); - if (i >= MAX_CLIENTS) - Host_EndGame ("CL_ParseServerMessage: svc_updatefrags > " - "MAX_SCOREBOARD"); - cl.players[i].frags = MSG_ReadShort (net_message); - break; - - case svc_updateping: - i = MSG_ReadByte (net_message); - if (i >= MAX_CLIENTS) - Host_EndGame ("CL_ParseServerMessage: svc_updateping > " - "MAX_SCOREBOARD"); - cl.players[i].ping = MSG_ReadShort (net_message); - break; - - case svc_updatepl: - i = MSG_ReadByte (net_message); - if (i >= MAX_CLIENTS) - Host_EndGame ("CL_ParseServerMessage: svc_updatepl > " - "MAX_SCOREBOARD"); - cl.players[i].pl = MSG_ReadByte (net_message); - break; - - case svc_updateentertime: - // time is sent over as seconds ago - i = MSG_ReadByte (net_message); - if (i >= MAX_CLIENTS) - Host_EndGame ("CL_ParseServerMessage: svc_updateentertime " - "> MAX_SCOREBOARD"); - cl.players[i].entertime = realtime - MSG_ReadFloat - (net_message); - break; - - case svc_spawnbaseline: - i = MSG_ReadShort (net_message); - CL_ParseBaseline (&cl_baselines[i]); - break; - case svc_spawnstatic: - CL_ParseStatic (); - break; - case svc_temp_entity: - CL_ParseTEnt (); - break; - - case svc_killedmonster: - cl.stats[STAT_MONSTERS]++; - break; - - case svc_foundsecret: - cl.stats[STAT_SECRETS]++; - break; - - case svc_updatestat: - i = MSG_ReadByte (net_message); - j = MSG_ReadByte (net_message); - CL_SetStat (i, j); - break; - case svc_updatestatlong: - i = MSG_ReadByte (net_message); - j = MSG_ReadLong (net_message); - CL_SetStat (i, j); - break; - - case svc_spawnstaticsound: - CL_ParseStaticSound (); - break; - - case svc_cdtrack: - cl.cdtrack = MSG_ReadByte (net_message); - CDAudio_Play ((byte) cl.cdtrack, true); - break; - - case svc_intermission: - Con_DPrintf ("svc_intermission\n"); - cl.intermission = 1; - cl.completed_time = realtime; - vid.recalc_refdef = true; // go to full screen - Con_DPrintf ("intermission simorg: "); - for (i = 0; i < 3; i++) { - cl.simorg[i] = MSG_ReadCoord (net_message); - Con_DPrintf ("%f ", cl.simorg[i]); - } - Con_DPrintf ("\nintermission simangles: "); - for (i = 0; i < 3; i++) { - cl.simangles[i] = MSG_ReadAngle (net_message); - Con_DPrintf ("%f ", cl.simangles[i]); - } - Con_DPrintf ("\n"); - VectorCopy (vec3_origin, cl.simvel); - break; - - case svc_finale: - cl.intermission = 2; - cl.completed_time = realtime; - vid.recalc_refdef = true; // go to full screen - SCR_CenterPrint (MSG_ReadString (net_message)); - break; - - case svc_sellscreen: - Cmd_ExecuteString ("help", src_command); - break; - - case svc_smallkick: - cl.punchangle = -2; - break; - case svc_bigkick: - cl.punchangle = -4; - break; - - case svc_muzzleflash: - CL_MuzzleFlash (); - break; - - case svc_updateuserinfo: - CL_UpdateUserinfo (); - break; - - case svc_setinfo: - CL_SetInfo (); - break; - - case svc_serverinfo: - CL_ServerInfo (); - break; - - case svc_download: - CL_ParseDownload (); - break; - - case svc_playerinfo: - CL_ParsePlayerinfo (); - break; - - case svc_nails: - CL_ParseProjectiles (); - break; - - case svc_chokecount: // some preceding packets were choked - i = MSG_ReadByte (net_message); - for (j = 0; j < i; j++) - cl. - frames[(cls.netchan.incoming_acknowledged - 1 - j) & - UPDATE_MASK].receivedtime = -2; - break; - - case svc_modellist: - CL_ParseModellist (); - break; - - case svc_soundlist: - CL_ParseSoundlist (); - break; - - case svc_packetentities: - CL_ParsePacketEntities (false); - break; - - case svc_deltapacketentities: - CL_ParsePacketEntities (true); - break; - - case svc_maxspeed: - movevars.maxspeed = MSG_ReadFloat (net_message); - break; - - case svc_entgravity: - movevars.entgravity = MSG_ReadFloat (net_message); - break; - - case svc_setpause: - cl.paused = MSG_ReadByte (net_message); - if (cl.paused) - CDAudio_Pause (); - else - CDAudio_Resume (); + Host_NetError ("CL_ParseServerMessage: Illegible " + "server message"); break; + case svc_nop: CL_ParseNOP (); break; + case svc_disconnect: CL_ParseDisconnect (); break; + case svc_print: CL_ParsePrint (); break; + case svc_centerprint: CL_ParseCenterprint (); break; + case svc_stufftext: CL_ParseStufftext (); break; + case svc_damage: CL_ParseDamage (); break; + case svc_serverdata: CL_ParseServerData (); break; + case svc_setangle: CL_ParseSetAngle (); break; + case svc_lightstyle: CL_ParseLightStyle (); break; + case svc_sound: CL_ParseSound (); break; + case svc_stopsound: CL_ParseStopSound (); break; + case svc_updatefrags: CL_ParseUpdateFrags (); break; + case svc_updateping: CL_ParseUpdatePing (); break; + case svc_updatepl: CL_ParseUpdatePL (); break; + case svc_updateentertime: CL_ParseUpdateEnterTime (); break; + case svc_spawnbaseline: CL_ParseSpawnBaseline (); break; + case svc_spawnstatic: CL_ParseStatic (); break; + case svc_temp_entity: CL_ParseTEnt (); break; + case svc_killedmonster: CL_ParseKilledMonster (); break; + case svc_foundsecret: CL_ParseFoundSecret (); break; + case svc_updatestat: CL_ParseUpdateStat (); break; + case svc_updatestatlong: CL_ParseUpdateStatLong (); break; + case svc_spawnstaticsound: CL_ParseStaticSound (); break; + case svc_cdtrack: CL_ParseCDTrack (); break; + case svc_intermission: CL_ParseIntermission (); break; + case svc_finale: CL_ParseFinale (); break; + case svc_sellscreen: CL_ParseSellScreen (); break; + case svc_smallkick: CL_ParseSmallKick (); break; + case svc_bigkick: CL_ParseBigKick (); break; + case svc_muzzleflash: CL_ParseMuzzleFlash (); break; + case svc_updateuserinfo: CL_ParseUpdateUserInfo (); break; + case svc_setinfo: CL_ParseSetInfo (); break; + case svc_serverinfo: CL_ParseServerInfo (); break; + case svc_download: CL_ParseDownload (); break; + case svc_playerinfo: CL_ParsePlayerinfo (); break; + case svc_nails: CL_ParseProjectiles (); break; + case svc_chokecount: CL_ParseChokeCount (); break; + case svc_modellist: CL_ParseModellist (); break; + case svc_soundlist: CL_ParseSoundlist (); break; + case svc_packetentities: CL_ParsePacketEntities (); break; + case svc_deltapacketentities: CL_ParseDeltaPacketEntities (); break; + case svc_maxspeed: CL_ParseMaxSpeed (); break; + case svc_entgravity: CL_ParseEntGravity (); break; + case svc_setpause: CL_ParseSetPause (); break; } } diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 2abeb267d..bb3fb1202 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -206,7 +206,7 @@ CL_NewTranslation (int slot, skin_t *skin) player_info_t *player; if (slot > MAX_CLIENTS) - Host_EndGame ("CL_NewTranslation: slot > MAX_CLIENTS"); + Host_NetError ("CL_NewTranslation: slot > MAX_CLIENTS"); player = &cl.players[slot]; if (!player->name[0]) diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index cd9b61243..4aaad4618 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -50,6 +50,8 @@ static const char rcsid[] = #include "cl_main.h" #include "cl_tent.h" #include "client.h" +#include "host.h" +#include "net_svc.h" #include "r_dynamic.h" #define MAX_BEAMS 8 @@ -182,42 +184,37 @@ CL_AllocExplosion (void) } void -CL_ParseBeam (model_t *m) +CL_ParseBeam (net_svc_tempentity_t *tempentity, model_t *m) { beam_t *b; - int ent, i; - vec3_t start, end; + int i; - ent = MSG_ReadShort (net_message); - - start[0] = MSG_ReadCoord (net_message); - start[1] = MSG_ReadCoord (net_message); - start[2] = MSG_ReadCoord (net_message); - - end[0] = MSG_ReadCoord (net_message); - end[1] = MSG_ReadCoord (net_message); - end[2] = MSG_ReadCoord (net_message); + if (tempentity->beamentity >= MAX_EDICTS) { + Host_NetError ("CL_ParseBeam: beamentity %i >= MAX_EDICTS", + tempentity->beamentity); + return; + } // override any beam with the same entity for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) - if (b->entity == ent) { - b->entity = ent; + if (b->entity == tempentity->beamentity) { + b->entity = tempentity->beamentity; b->model = m; b->endtime = cl.time + 0.2; b->seed = rand(); - VectorCopy (start, b->start); - VectorCopy (end, b->end); + VectorCopy (tempentity->position, b->start); + VectorCopy (tempentity->beamend, b->end); return; } // find a free beam for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) { if (!b->model || b->endtime < cl.time) { - b->entity = ent; + b->entity = tempentity->beamentity; b->model = m; b->endtime = cl.time + 0.2; b->seed = rand(); - VectorCopy (start, b->start); - VectorCopy (end, b->end); + VectorCopy (tempentity->position, b->start); + VectorCopy (tempentity->beamend, b->end); return; } } @@ -227,79 +224,66 @@ CL_ParseBeam (model_t *m) void CL_ParseTEnt (void) { - byte type; dlight_t *dl; explosion_t *ex; - int colorStart, colorLength, rnd; - int cnt = -1; - vec3_t pos; + int rnd; + net_svc_tempentity_t tempentity; - type = MSG_ReadByte (net_message); - switch (type) { + if (NET_SVC_TempEntity_Parse (&tempentity, net_message)) { + Host_NetError ("CL_ParseTEnt: Bad Read\n"); + return; + } + + switch (tempentity.type) { case TE_WIZSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_RunSpikeEffect (pos, prot_to_rend[type]); - S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); + R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]); + S_StartSound (-1, 0, cl_sfx_wizhit, tempentity.position, 1, 1); break; case TE_KNIGHTSPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_RunSpikeEffect (pos, prot_to_rend[type]); - S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); + R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]); + S_StartSound (-1, 0, cl_sfx_knighthit, tempentity.position, 1, 1); break; case TE_SPIKE: // spike hitting wall - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_RunSpikeEffect (pos, prot_to_rend[type]); + R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]); if (rand () % 5) - S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_tink1, tempentity.position, 1, 1); else { rnd = rand () & 3; if (rnd == 1) - S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric1, tempentity.position, 1, 1); else if (rnd == 2) - S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric2, tempentity.position, 1, 1); else - S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric3, tempentity.position, 1, 1); } break; case TE_SUPERSPIKE: // super spike hitting wall - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_RunSpikeEffect (pos, prot_to_rend[type]); + R_RunSpikeEffect (tempentity.position, prot_to_rend[tempentity.type]); if (rand () % 5) - S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_tink1, tempentity.position, 1, 1); else { rnd = rand () & 3; if (rnd == 1) - S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric1, tempentity.position, 1, 1); else if (rnd == 2) - S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric2, tempentity.position, 1, 1); else - S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_ric3, tempentity.position, 1, 1); } break; case TE_EXPLOSION: // rocket explosion // particles - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_ParticleExplosion (pos); + R_ParticleExplosion (tempentity.position); // light dl = R_AllocDlight (0); - VectorCopy (pos, dl->origin); + VectorCopy (tempentity.position, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; @@ -308,94 +292,78 @@ CL_ParseTEnt (void) dl->color[2] = 0.24; // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1); // sprite ex = CL_AllocExplosion (); - VectorCopy (pos, ex->ent.origin); + VectorCopy (tempentity.position, ex->ent.origin); ex->start = cl.time; ex->ent.model = cl_spr_explod; break; case TE_TAREXPLOSION: // tarbaby explosion - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_BlobExplosion (pos); + R_BlobExplosion (tempentity.position); - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1); break; case TE_LIGHTNING1: // lightning bolts - CL_ParseBeam (cl_mod_bolt); + CL_ParseBeam (&tempentity, cl_mod_bolt); break; case TE_LIGHTNING2: // lightning bolts - CL_ParseBeam (cl_mod_bolt2); + CL_ParseBeam (&tempentity, cl_mod_bolt2); break; case TE_LIGHTNING3: // lightning bolts - CL_ParseBeam (cl_mod_bolt3); + CL_ParseBeam (&tempentity, cl_mod_bolt3); break; // PGM 01/21/97 case TE_BEAM: // grappling hook beam - CL_ParseBeam (Mod_ForName ("progs/beam.mdl", true)); + CL_ParseBeam (&tempentity, Mod_ForName ("progs/beam.mdl", true)); break; // PGM 01/21/97 case TE_LAVASPLASH: - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_LavaSplash (pos); + R_LavaSplash (tempentity.position); break; case TE_TELEPORT: - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_TeleportSplash (pos); + R_TeleportSplash (tempentity.position); break; case TE_EXPLOSION2: // color mapped explosion - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - colorStart = MSG_ReadByte (net_message); - colorLength = MSG_ReadByte (net_message); - R_ParticleExplosion2 (pos, colorStart, colorLength); + R_ParticleExplosion2 (tempentity.position, + tempentity.colorstart, + tempentity.colorlength); dl = R_AllocDlight (0); - VectorCopy (pos, dl->origin); + VectorCopy (tempentity.position, dl->origin); dl->radius = 350; dl->die = cl.time + 0.5; dl->decay = 300; - dl->color[0] = vid_basepal[(colorStart + (rand() % colorLength)) * - 3] * (1.0 / 255.0); - dl->color[1] = vid_basepal[(colorStart + (rand() % colorLength)) * - 3 + 1] * (1.0 / 255.0); - dl->color[2] = vid_basepal[(colorStart + (rand() % colorLength)) * - 3 + 2] * (1.0 / 255.0); - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + dl->color[0] = vid_basepal[(tempentity.colorstart + + (rand() % tempentity.colorlength)) + * 3] * (1.0 / 255.0); + dl->color[1] = vid_basepal[(tempentity.colorstart + + (rand() % tempentity.colorlength)) + * 3 + 1] * (1.0 / 255.0); + dl->color[2] = vid_basepal[(tempentity.colorstart + + (rand() % tempentity.colorlength)) + * 3 + 2] * (1.0 / 255.0); + S_StartSound (-1, 0, cl_sfx_r_exp3, tempentity.position, 1, 1); break; case TE_GUNSHOT: // bullet hitting wall case TE_BLOOD: // bullets hitting body - cnt = MSG_ReadByte (net_message) * 20; - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - R_RunPuffEffect (pos, prot_to_rend[type], cnt); + R_RunPuffEffect (tempentity.position, prot_to_rend[tempentity.type], + tempentity.gunshotcount * 20); break; case TE_LIGHTNINGBLOOD: // lightning hitting body - pos[0] = MSG_ReadCoord (net_message); - pos[1] = MSG_ReadCoord (net_message); - pos[2] = MSG_ReadCoord (net_message); - // light dl = R_AllocDlight (0); - VectorCopy (pos, dl->origin); + VectorCopy (tempentity.position, dl->origin); dl->radius = 150; dl->die = cl.time + 0.1; dl->decay = 200; @@ -403,11 +371,11 @@ CL_ParseTEnt (void) dl->color[1] = 0.40; dl->color[2] = 0.65; - R_RunPuffEffect (pos, prot_to_rend[type], cnt); + R_RunPuffEffect (tempentity.position, prot_to_rend[tempentity.type], 0); break; default: - Sys_Error ("CL_ParseTEnt: bad type"); + Sys_Error ("CL_ParseTEnt: bad tempentity.type %i", tempentity.type); } } diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 6287d1406..04efe9dd4 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -45,6 +45,7 @@ static const char rcsid[] = #include "client.h" #include "compat.h" #include "host.h" +#include "net_svc.h" #include "pmove.h" #include "view.h" @@ -240,18 +241,18 @@ V_DriftPitch (void) /* PALETTE FLASHES */ void -V_ParseDamage (void) +CL_ParseDamage (void) { float count, side; - int armor, blood, i; - vec3_t forward, from, right, up; + vec3_t forward, right, up; + net_svc_damage_t damage; - armor = MSG_ReadByte (net_message); - blood = MSG_ReadByte (net_message); - for (i = 0; i < 3; i++) - from[i] = MSG_ReadCoord (net_message); + if (NET_SVC_Damage_Parse (&damage, net_message)) { + Host_NetError ("CL_ParseDamage: Bad Read\n"); + return; + } - count = blood * 0.5 + armor * 0.5; + count = damage.blood * 0.5 + damage.armor * 0.5; if (count < 10) count = 10; @@ -265,11 +266,11 @@ V_ParseDamage (void) cl.cshifts[CSHIFT_DAMAGE].percent = bound (0, cl.cshifts[CSHIFT_DAMAGE].percent, 150); - if (armor > blood) { + if (damage.armor > damage.blood) { cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100; cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100; - } else if (armor) { + } else if (damage.armor) { cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220; cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50; cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50; @@ -281,15 +282,15 @@ V_ParseDamage (void) } // calculate view angle kicks - VectorSubtract (from, cl.simorg, from); - VectorNormalize (from); + VectorSubtract (damage.from, cl.simorg, damage.from); + VectorNormalize (damage.from); AngleVectors (cl.simangles, forward, right, up); - side = DotProduct (from, right); + side = DotProduct (damage.from, right); v_dmg_roll = count * side * v_kickroll->value; - side = DotProduct (from, forward); + side = DotProduct (damage.from, forward); v_dmg_pitch = count * side * v_kickpitch->value; v_dmg_time = v_kicktime->value; diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index a5f393b63..aa83fa73f 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -1,11 +1,11 @@ /* - net_packetlog.c + net_packetlog.c - packet logging/parsing - for debugging and educational purposes + packet logging/parsing - for debugging and educational purposes - **EXPERIMENTAL** + **EXPERIMENTAL** - Copyright (C) 2000 Jukka Sorjonen + Copyright (C) 2000 Jukka Sorjonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -56,6 +56,7 @@ static const char rcsid[] = #include "compat.h" #include "net.h" +#include "net_svc.h" #include "protocol.h" #include "server.h" @@ -64,87 +65,12 @@ cvar_t *net_loglevel; int Net_LogStart (const char *fname); -void Analyze_Server_Packet (const byte * data, int len); -void Analyze_Client_Packet (const byte * data, int len); +void Analyze_Server_Packet (const byte *data, int len); +void Analyze_Client_Packet (const byte *data, int len); void Parse_Server_Packet (void); void Parse_Client_Packet (void); void Net_LogStop (void); -// note: this is SUPPOSED to be duplicate, like many others -const char *svc_string[] = { - "svc_bad", - "svc_nop", - "svc_disconnect", - "svc_updatestat", - "svc_version", // [long] server version - "svc_setview", // [short] entity number - "svc_sound", // - "svc_time", // [float] server time - "svc_print", // [string] null terminated string - "svc_stufftext", // [string] stuffed into client's - // console buffer the string - // should be \n terminated - "svc_setangle", // [vec3] set the view angle to this - // absolute value - "svc_serverdata", // [long] version ... - "svc_lightstyle", // [byte] [string] - "svc_updatename", // [byte] [string] - "svc_updatefrags", // [byte] [short] - "svc_clientdata", // - "svc_stopsound", // - "svc_updatecolors", // [byte] [byte] - "svc_particle", // [vec3] - "svc_damage", // [byte] impact [byte] blood [vec3] - // from - "svc_spawnstatic", - "svc_spawnbinary", - "svc_spawnbaseline", - "svc_temp_entity", // - "svc_setpause", - "svc_signonnum", - "svc_centerprint", - "svc_killedmonster", - "svc_foundsecret", - "svc_spawnstaticsound", - "svc_intermission", - "svc_finale", // [string] music [string] text - "svc_cdtrack", // [byte] track [byte] looptrack - "svc_sellscreen", - "svc_smallkick", // Quake svc_cutscene - "svc_bigkick", - "svc_updateping", - "svc_updateentertime", - "svc_updatestatlong", - "svc_muzzleflash", - "svc_updateuserinfo", - "svc_download", - "svc_playerinfo", - "svc_nails", - "svc_chokecount", - "svc_modellist", - "svc_soundlist", - "svc_packetentities", - "svc_deltapacketentities", - "svc_maxspeed", - "svc_entgravity", - "svc_setinfo", - "svc_serverinfo", - "svc_updatepl", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL" -}; - const char *clc_string[] = { "clc_bad", "clc_nop", @@ -169,7 +95,6 @@ const char *clc_string[] = { #define svc_particle 18 // [vec3] #define svc_signonnum 25 // [byte] used for the signon // sequence -static VFile *_stdout; static VFile *Net_PacketLog; static const char **Net_sound_precache; static sizebuf_t _packet; @@ -190,11 +115,12 @@ Net_LogPrintf (char *fmt, ...) va_start (argptr, fmt); vsnprintf (text, sizeof (text), fmt, argptr); va_end (argptr); - if (!Net_PacketLog) - return; - Qprintf (Net_PacketLog, "%s", text); - Qflush (Net_PacketLog); + if (Net_PacketLog) { + Qprintf (Net_PacketLog, "%s", text); + Qflush (Net_PacketLog); + } else + Con_Printf ("%s", text); } int @@ -304,104 +230,113 @@ Log_Outgoing_Packet (const char *p, int len) return; } -void +qboolean Log_Delta(int bits) { entity_state_t to; int i; - Net_LogPrintf ("\n\t"); + Net_LogPrintf ("\n\t<%06x> ", MSG_GetReadCount (&packet) - 2); + if (!bits) { + Net_LogPrintf ("End"); + return 1; + } // set everything to the state we are delta'ing from to.number = bits & 511; bits &= ~511; + Net_LogPrintf ("Ent: %d", to.number); + + if (bits & U_REMOVE) + Net_LogPrintf (" U_REMOVE"); + if (bits & U_MOREBITS) { // read in the low order bits i = MSG_ReadByte (&packet); bits |= i; + Net_LogPrintf (" U_MOREBITS"); } // LordHavoc: Endy neglected to mark this as being part of the QSG // version 2 stuff... if (bits & U_EXTEND1) { bits |= MSG_ReadByte (&packet) << 16; - if (bits & U_EXTEND2) + Net_LogPrintf (" U_EXTEND1"); + if (bits & U_EXTEND2) { bits |= MSG_ReadByte (&packet) << 24; + Net_LogPrintf (" U_EXTEND2"); + } } to.flags = bits; if (bits & U_MODEL) - Net_LogPrintf (" MdlIdx: %d", MSG_ReadByte (&packet)); + Net_LogPrintf (" MdlIdx: %d", MSG_ReadByte (&packet)); - if (bits & U_FRAME) { - to.frame = MSG_ReadByte (&packet); - Net_LogPrintf (" Frame: %d", to.frame); - } + if (bits & U_FRAME) { + to.frame = MSG_ReadByte (&packet); + Net_LogPrintf (" Frame: %d", to.frame); + } if (bits & U_COLORMAP) - Net_LogPrintf (" Colormap: %d", MSG_ReadByte (&packet)); + Net_LogPrintf (" Colormap: %d", MSG_ReadByte (&packet)); if (bits & U_SKIN) - Net_LogPrintf (" Skinnum: %d", MSG_ReadByte (&packet)); + Net_LogPrintf (" Skinnum: %d", MSG_ReadByte (&packet)); - if (bits & U_EFFECTS) { - to.effects = MSG_ReadByte (&packet); - Net_LogPrintf (" Effects: %d", to.effects); - } + if (bits & U_EFFECTS) { + to.effects = MSG_ReadByte (&packet); + Net_LogPrintf (" Effects: %d", to.effects); + } if (bits & U_ORIGIN1) - Net_LogPrintf (" X: %f", MSG_ReadCoord (&packet)); + Net_LogPrintf (" X: %f", MSG_ReadCoord (&packet)); if (bits & U_ANGLE1) - Net_LogPrintf (" Pitch: %d", MSG_ReadAngle (&packet)); + Net_LogPrintf (" Pitch: %d", MSG_ReadAngle (&packet)); if (bits & U_ORIGIN2) - Net_LogPrintf (" Y: %f", MSG_ReadCoord (&packet)); + Net_LogPrintf (" Y: %f", MSG_ReadCoord (&packet)); if (bits & U_ANGLE2) - Net_LogPrintf (" Yaw: %d", MSG_ReadAngle (&packet)); + Net_LogPrintf (" Yaw: %d", MSG_ReadAngle (&packet)); if (bits & U_ORIGIN3) - Net_LogPrintf (" Z: %f", MSG_ReadCoord (&packet)); + Net_LogPrintf (" Z: %f", MSG_ReadCoord (&packet)); if (bits & U_ANGLE3) - Net_LogPrintf (" Roll: %d", MSG_ReadAngle (&packet)); + Net_LogPrintf (" Roll: %d", MSG_ReadAngle (&packet)); // Ender (QSG - Begin) if (bits & U_ALPHA) - Net_LogPrintf(" Alpha: %d", MSG_ReadByte (&packet)); + Net_LogPrintf(" Alpha: %d", MSG_ReadByte (&packet)); if (bits & U_SCALE) - Net_LogPrintf(" Scale: %d", MSG_ReadByte (&packet)); + Net_LogPrintf(" Scale: %d", MSG_ReadByte (&packet)); if (bits & U_EFFECTS2) - Net_LogPrintf(" U_EFFECTS2: %d", (to.effects & 0xFF) | (MSG_ReadByte (&packet) << 8)); + Net_LogPrintf(" U_EFFECTS2: %d", (to.effects & 0xFF) | (MSG_ReadByte (&packet) << 8)); if (bits & U_GLOWSIZE) - Net_LogPrintf(" GlowSize: %d", MSG_ReadByte (&packet)); + Net_LogPrintf(" GlowSize: %d", MSG_ReadByte (&packet)); if (bits & U_GLOWCOLOR) - Net_LogPrintf(" ColorGlow: %d", MSG_ReadByte (&packet)); + Net_LogPrintf(" ColorGlow: %d", MSG_ReadByte (&packet)); if (bits & U_COLORMOD) - Net_LogPrintf(" Colormod: %d", MSG_ReadByte (&packet)); + Net_LogPrintf(" Colormod: %d", MSG_ReadByte (&packet)); if (bits & U_FRAME2) - Net_LogPrintf(" Uframe2: %d", ((to.frame & 0xFF) | (MSG_ReadByte (&packet) << 8))); + Net_LogPrintf(" Uframe2: %d", ((to.frame & 0xFF) | (MSG_ReadByte (&packet) << 8))); // Ender (QSG - End) - return; + return 0; } void -Analyze_Server_Packet (const byte * data, int len) +Analyze_Server_Packet (const byte *data, int len) { - if (!Net_PacketLog) - Net_PacketLog = _stdout; packet.message->data = (byte*)data; packet.message->cursize = len; MSG_BeginReading (&packet); Parse_Server_Packet (); - if (Net_PacketLog == _stdout) - Net_PacketLog = NULL; } @@ -438,10 +373,11 @@ Parse_Server_Packet () if (c == -1) break; // Net_LogPrintf("\n<%ld,%ld> ",seq1 & 0x7FFFFFFF,seq2 & 0x7FFFFFFF); - Net_LogPrintf ("<%06x> [0x%02x] ", MSG_GetReadCount (&packet), c); + Net_LogPrintf ("<%06x> [0x%02x] ", + MSG_GetReadCount (&packet) - 1, c); if (c < 53) - Net_LogPrintf ("%s: ", svc_string[c]); + Net_LogPrintf ("%s: ", NET_SVC_GetString (c)); // else Net_LogPrintf("(UNK: %d): ",c); if (MSG_GetReadCount (&packet) > packet.message->cursize) @@ -623,7 +559,7 @@ Parse_Server_Packet () Net_LogPrintf ("**QW OBSOLETE**"); break; case svc_centerprint: - Net_LogPrintf ("%s\n", MSG_ReadString (&packet)); + Net_LogPrintf ("%s", MSG_ReadString (&packet)); break; case svc_killedmonster: break; @@ -794,22 +730,20 @@ Parse_Server_Packet () else Net_LogPrintf ("\n\t*End of sound list*"); break; + case svc_deltapacketentities: + Net_LogPrintf ("from: %d", MSG_ReadByte (&packet)); + // intentional fallthrough case svc_packetentities: while (1) { mask1 = (unsigned short) MSG_ReadShort(&packet); if (packet.badread) { - Net_LogPrintf ("Badread\n"); + Net_LogPrintf (" Badread\n"); return; } - if (!mask1) break; - if (mask1 & U_REMOVE) Net_LogPrintf("UREMOVE "); - Log_Delta(mask1); + if (Log_Delta(mask1)) + break; } break; - case svc_deltapacketentities: - Net_LogPrintf ("idx: %d", MSG_ReadByte (&packet)); - return; - break; case svc_maxspeed: Net_LogPrintf ("%f", MSG_ReadFloat (&packet)); break; @@ -839,16 +773,12 @@ Parse_Server_Packet () } void -Analyze_Client_Packet (const byte * data, int len) +Analyze_Client_Packet (const byte *data, int len) { - if (!Net_PacketLog) - Net_PacketLog = _stdout; packet.message->data = (byte*)data; packet.message->cursize = len; MSG_BeginReading (&packet); Parse_Client_Packet (); - if (Net_PacketLog == _stdout) - Net_PacketLog = NULL; } void @@ -962,7 +892,7 @@ Net_PacketLog_f (cvar_t *var) void Net_PacketLog_Zap_f (void) { - if (Net_PacketLog && Net_PacketLog != _stdout) { + if (Net_PacketLog) { Con_Printf ("truncating packet logfile: %s\n", "qfpacket.log"); Qseek (Net_PacketLog, 0, 0); Qwrite (Net_PacketLog, 0, 0); @@ -980,8 +910,6 @@ Net_Log_Init (const char **sound_precache) { Net_sound_precache = sound_precache; - _stdout = Qdopen (1, "wt"); // create a QFile of stdout - net_packetlog = Cvar_Get ("net_packetlog", "0", CVAR_NONE, Net_PacketLog_f, "enable/disable packet logging"); diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 6a092ce8e..8fcffb20b 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -52,6 +52,7 @@ static const char rcsid[] = #include "bothdefs.h" #include "compat.h" +#include "net_svc.h" #include "server.h" #include "sv_progs.h" @@ -829,12 +830,15 @@ SV_Heartbeat_f (void) void SV_SendServerInfoChange (const char *key, const char *value) { + net_svc_serverinfo_t block; + if (!sv.state) return; + block.key = key; + block.value = value; MSG_WriteByte (&sv.reliable_datagram, svc_serverinfo); - MSG_WriteString (&sv.reliable_datagram, key); - MSG_WriteString (&sv.reliable_datagram, value); + NET_SVC_ServerInfo_Emit (&block, &sv.reliable_datagram); } /* diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index 0c5229cb6..8e9f47b9b 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -42,6 +42,7 @@ static const char rcsid[] = #include "compat.h" #include "msg_ucmd.h" +#include "net_svc.h" #include "server.h" #include "sv_progs.h" @@ -125,51 +126,29 @@ SV_AddNailUpdate (edict_t *ent) void SV_EmitNailUpdate (sizebuf_t *msg) { - byte bits[6]; // [48 bits] xyzpy 12 12 12 4 8 - int i, n, p, x, y, z, yaw; - edict_t *ent; + int i; + net_svc_nails_t block; if (!numnails) return; - MSG_WriteByte (msg, svc_nails); - MSG_WriteByte (msg, numnails); + block.numnails = numnails; - for (n = 0; n < numnails; n++) { - ent = nails[n]; - x = (int) (SVvector (ent, origin)[0] + 4096) >> 1; - y = (int) (SVvector (ent, origin)[1] + 4096) >> 1; - z = (int) (SVvector (ent, origin)[2] + 4096) >> 1; - p = (int) (16 * SVvector (ent, angles)[0] / 360) & 15; - yaw = (int) (256 * SVvector (ent, angles)[1] / 360) & 255; - - bits[0] = x; - bits[1] = (x >> 8) | (y << 4); - bits[2] = (y >> 4); - bits[3] = z; - bits[4] = (z >> 8) | (p << 4); - bits[5] = yaw; - - for (i = 0; i < 6; i++) - MSG_WriteByte (msg, bits[i]); + for (i = 0; i < numnails; i++) { + VectorCopy (SVvector (nails[i], origin), block.nails[i].origin); + VectorCopy (SVvector (nails[i], angles), block.nails[i].angles); } + + MSG_WriteByte (msg, svc_nails); + NET_SVC_Nails_Emit (&block, msg); } -/* - SV_WriteDelta - - Writes part of a packetentities message. - Can delta from either a baseline or a previous packet_entity -*/ -void -SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, - qboolean force, int stdver) +unsigned int +SV_EntityState_Diff (entity_state_t *from, entity_state_t *to) { - int bits, i; - float miss; - - // send an update - bits = 0; + int i; + float miss; + unsigned int bits = 0; for (i = 0; i < 3; i++) { miss = to->origin[i] - from->origin[i]; @@ -203,7 +182,7 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, // LordHavoc: cleaned up Endy's coding style, and added missing effects // Ender (QSG - Begin) - if (stdver > 1) { +// if (stdver > 1) { if (to->alpha != from->alpha) bits |= U_ALPHA; @@ -218,20 +197,44 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, if (to->colormod != from->colormod) bits |= U_COLORMOD; - } +// } - if (bits >= 16777216) +// if (bits >= 16777216) + if (bits & U_GROUP_EXTEND2) bits |= U_EXTEND2; - if (bits >= 65536) +// if (bits >= 65536) + if (bits & U_GROUP_EXTEND1) bits |= U_EXTEND1; // Ender (QSG - End) - if (bits & 511) + +// if (bits & 511) + if (bits & U_GROUP_MOREBITS) bits |= U_MOREBITS; if (to->flags & U_SOLID) bits |= U_SOLID; + return bits; +} + +/* + SV_WriteDelta + + Writes part of a packetentities message. + Can delta from either a baseline or a previous packet_entity +*/ +void +SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, + qboolean force, int stdver) +{ + unsigned int bits; + + // send an update + bits = SV_EntityState_Diff (from, to); + if (stdver <= 1) + bits &= U_VERSION_ID; // use old the original fields, no extensions + // write the message if (!to->number) SV_Error ("Unset entity number"); @@ -240,10 +243,7 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, if (!bits && !force) return; // nothing to send! - i = to->number | (bits & ~511); - if (i & U_REMOVE) - Sys_Error ("U_REMOVE"); - MSG_WriteShort (msg, i); + MSG_WriteShort (msg, to->number | (bits & ~511)); if (bits & U_MOREBITS) MSG_WriteByte (msg, bits & 255); @@ -302,80 +302,118 @@ SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, /* SV_EmitPacketEntities - Writes a delta update of a packet_entities_t to the message. + Writes an update of a packet_entities_t to the message. */ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg) { - int newindex, oldindex, newnum, oldnum, oldmax; - edict_t *ent; - client_frame_t *fromframe; + int index; + entity_state_t *baseline; + net_svc_packetentities_t block; + + block.numwords = block.numdeltas = to->num_entities; + + for (index = 0; index < to->num_entities; index++) { + baseline = EDICT_NUM (&sv_pr_state, + to->entities[index].number)->data; + block.deltas[index] = to->entities[index]; + block.deltas[index].flags = + SV_EntityState_Diff (baseline, &to->entities[index]); + + // check if it's a client that doesn't support QSG2 + if (client->stdver <= 1) + block.deltas[index].flags &= U_VERSION_ID; + + block.words[index] = to->entities[index].number | + (block.deltas[index].flags & ~511); + } + + block.words[index] = 0; + MSG_WriteByte (msg, svc_packetentities); + NET_SVC_PacketEntities_Emit (&block, msg); +} + +/* + SV_EmitDeltaPacketEntities + + Writes a delta update of a packet_entities_t to the message. +*/ +void +SV_EmitDeltaPacketEntities (client_t *client, packet_entities_t *to, + sizebuf_t *msg) +{ + int newindex, oldindex, newnum, oldnum; + int word; + entity_state_t *baseline; packet_entities_t *from; + net_svc_deltapacketentities_t block; // this is the frame that we are going to delta update from - if (client->delta_sequence != -1) { - fromframe = &client->frames[client->delta_sequence & UPDATE_MASK]; - from = &fromframe->entities; - oldmax = from->num_entities; + from = &client->frames[client->delta_sequence & UPDATE_MASK].entities; - MSG_WriteByte (msg, svc_deltapacketentities); - MSG_WriteByte (msg, client->delta_sequence); - } else { - oldmax = 0; // no delta update - from = NULL; + block.from = client->delta_sequence; - MSG_WriteByte (msg, svc_packetentities); - } - - newindex = 0; - oldindex = 0; // SV_Printf ("---%i to %i ----\n", client->delta_sequence & UPDATE_MASK, // client->netchan.outgoing_sequence & UPDATE_MASK); - while (newindex < to->num_entities || oldindex < oldmax) { - newnum = - newindex >= to->num_entities ? 9999 : - to->entities[newindex].number; - oldnum = oldindex >= oldmax ? 9999 : from->entities[oldindex].number; + for (newindex = 0, oldindex = 0, word = 0; + newindex < to->num_entities || oldindex < from->num_entities; + word++) { + newnum = newindex >= to->num_entities ? + 9999 : to->entities[newindex].number; + oldnum = oldindex >= from->num_entities ? + 9999 : from->entities[oldindex].number; - if (newnum == oldnum) { // delta update from old position + if (newnum == oldnum) { // delta update from old position // SV_Printf ("delta %i\n", newnum); - SV_WriteDelta (&from->entities[oldindex], &to->entities[newindex], - msg, false, client->stdver); + block.deltas[newindex] = to->entities[newindex]; + block.deltas[newindex].flags = + SV_EntityState_Diff (&from->entities[oldindex], + &to->entities[newindex]); + + // check if it's a client that doesn't support QSG2 + if (client->stdver <= 1) + block.deltas[newindex].flags &= U_VERSION_ID; + + block.words[word] = newnum | (block.deltas[newindex].flags & ~511); + oldindex++; newindex++; - continue; - } - - if (newnum < oldnum) { // this is a new entity, send it from - // the baseline - ent = EDICT_NUM (&sv_pr_state, newnum); + } else if (newnum < oldnum) { // this is a new entity, send + // it from the baseline + baseline = EDICT_NUM (&sv_pr_state, newnum)->data; // SV_Printf ("baseline %i\n", newnum); - SV_WriteDelta (ent->data, &to->entities[newindex], msg, true, - client->stdver); - newindex++; - continue; - } + block.deltas[newindex] = to->entities[newindex]; + block.deltas[newindex].flags = + SV_EntityState_Diff (baseline, &to->entities[newindex]); - if (newnum > oldnum) { // the old entity isn't present in - // the new message + // check if it's a client that doesn't support QSG2 + if (client->stdver <= 1) + block.deltas[newindex].flags &= U_VERSION_ID; + + block.words[word] = newnum | (block.deltas[newindex].flags & ~511); + + newindex++; + } else if (newnum > oldnum) { // the old entity isn't + // present in the new message // SV_Printf ("remove %i\n", oldnum); - MSG_WriteShort (msg, oldnum | U_REMOVE); + block.words[word] = oldnum | U_REMOVE; oldindex++; - continue; } } - MSG_WriteShort (msg, 0); // end of packetentities + block.words[word] = 0; + MSG_WriteByte (msg, svc_deltapacketentities); + NET_SVC_DeltaPacketEntities_Emit (&block, msg); } void SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs, sizebuf_t *msg) { - int i, j, msec, pflags; + int i, j; client_t *cl; edict_t *ent; - usercmd_t cmd; + net_svc_playerinfo_t block; for (j = 0, cl = svs.clients; j < MAX_CLIENTS; j++, cl++) { if (cl->state != cs_spawned) @@ -397,82 +435,63 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs, continue; // not visible } - pflags = PF_MSEC | PF_COMMAND; + block.flags = PF_MSEC | PF_COMMAND; if (SVfloat (ent, modelindex) != sv_playermodel) - pflags |= PF_MODEL; + block.flags |= PF_MODEL; for (i = 0; i < 3; i++) if (SVvector (ent, velocity)[i]) - pflags |= PF_VELOCITY1 << i; + block.flags |= PF_VELOCITY1 << i; if (SVfloat (ent, effects)) - pflags |= PF_EFFECTS; + block.flags |= PF_EFFECTS; if (SVfloat (ent, skin)) - pflags |= PF_SKINNUM; + block.flags |= PF_SKINNUM; if (SVfloat (ent, health) <= 0) - pflags |= PF_DEAD; + block.flags |= PF_DEAD; if (SVvector (ent, mins)[2] != -24) - pflags |= PF_GIB; + block.flags |= PF_GIB; if (cl->spectator) { // only sent origin and velocity to // spectators - pflags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3; + block.flags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3; } else if (ent == clent) { // don't send a lot of data on // personal entity - pflags &= ~(PF_MSEC | PF_COMMAND); + block.flags &= ~(PF_MSEC | PF_COMMAND); if (SVfloat (ent, weaponframe)) - pflags |= PF_WEAPONFRAME; + block.flags |= PF_WEAPONFRAME; } if (client->spec_track && client->spec_track - 1 == j && - SVfloat (ent, weaponframe)) pflags |= PF_WEAPONFRAME; + SVfloat (ent, weaponframe)) + block.flags |= PF_WEAPONFRAME; + + block.playernum = j; + + VectorCopy (SVvector (ent, origin), block.origin); + block.frame = SVfloat (ent, frame); + + block.msec = 1000 * (sv.time - cl->localtime); + if (block.msec > 255) + block.msec = 255; + + block.usercmd = cl->lastcmd; + if (SVfloat (ent, health) <= 0) { // don't show the corpse + // looking around... + block.usercmd.angles[0] = 0; + block.usercmd.angles[1] = SVvector (ent, angles)[1]; + block.usercmd.angles[0] = 0; + } + block.usercmd.buttons = 0; // never send buttons + block.usercmd.impulse = 0; // never send impulses + + VectorCopy (SVvector (ent, velocity), block.velocity); + block.modelindex = SVfloat (ent, modelindex); + block.skinnum = SVfloat (ent, skin); + block.effects = SVfloat (ent, effects); + block.weaponframe = SVfloat (ent, weaponframe); MSG_WriteByte (msg, svc_playerinfo); - MSG_WriteByte (msg, j); - MSG_WriteShort (msg, pflags); - - for (i = 0; i < 3; i++) - MSG_WriteCoord (msg, SVvector (ent, origin)[i]); - - MSG_WriteByte (msg, SVfloat (ent, frame)); - - if (pflags & PF_MSEC) { - msec = 1000 * (sv.time - cl->localtime); - if (msec > 255) - msec = 255; - MSG_WriteByte (msg, msec); - } - - if (pflags & PF_COMMAND) { - cmd = cl->lastcmd; - - if (SVfloat (ent, health) <= 0) { // don't show the corpse - // looking around... - cmd.angles[0] = 0; - cmd.angles[1] = SVvector (ent, angles)[1]; - cmd.angles[0] = 0; - } - - cmd.buttons = 0; // never send buttons - cmd.impulse = 0; // never send impulses - - MSG_WriteDeltaUsercmd (msg, &nullcmd, &cmd); - } - - for (i = 0; i < 3; i++) - if (pflags & (PF_VELOCITY1 << i)) - MSG_WriteShort (msg, SVvector (ent, velocity)[i]); - - if (pflags & PF_MODEL) - MSG_WriteByte (msg, SVfloat (ent, modelindex)); - - if (pflags & PF_SKINNUM) - MSG_WriteByte (msg, SVfloat (ent, skin)); - - if (pflags & PF_EFFECTS) - MSG_WriteByte (msg, SVfloat (ent, effects)); - - if (pflags & PF_WEAPONFRAME) - MSG_WriteByte (msg, SVfloat (ent, weaponframe)); + NET_SVC_Playerinfo_Emit (&block, msg); } } @@ -591,8 +610,10 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg) // encode the packet entities as a delta from the // last packetentities acknowledged by the client - - SV_EmitPacketEntities (client, pack, msg); + if (client->delta_sequence != -1) + SV_EmitDeltaPacketEntities (client, pack, msg); + else + SV_EmitPacketEntities (client, pack, msg); // now add the specialized nail update SV_EmitNailUpdate (msg); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index eb08dc542..731e1625a 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -46,6 +46,7 @@ static const char rcsid[] = #include "compat.h" #include "crudefile.h" +#include "net_svc.h" #include "server.h" #include "sv_progs.h" #include "world.h" @@ -104,8 +105,9 @@ SV_FlushSignon (void) void SV_CreateBaseline (void) { - int i, entnum; + int entnum; edict_t *svent; + net_svc_spawnbaseline_t block; for (entnum = 0; entnum < sv.num_edicts; entnum++) { svent = EDICT_NUM (&sv_pr_state, entnum); @@ -143,19 +145,15 @@ SV_CreateBaseline (void) SV_FlushSignon (); // add to the message + block.num = entnum; + block.modelindex = ((entity_state_t*)svent->data)->modelindex; + block.frame = ((entity_state_t*)svent->data)->frame; + block.colormap = ((entity_state_t*)svent->data)->colormap; + block.skinnum = ((entity_state_t*)svent->data)->skinnum; + VectorCopy (((entity_state_t*)svent->data)->origin, block.origin); + VectorCopy (((entity_state_t*)svent->data)->angles, block.angles); MSG_WriteByte (&sv.signon, svc_spawnbaseline); - MSG_WriteShort (&sv.signon, entnum); - - MSG_WriteByte (&sv.signon, ((entity_state_t*)svent->data)->modelindex); - MSG_WriteByte (&sv.signon, ((entity_state_t*)svent->data)->frame); - MSG_WriteByte (&sv.signon, ((entity_state_t*)svent->data)->colormap); - MSG_WriteByte (&sv.signon, ((entity_state_t*)svent->data)->skinnum); - for (i = 0; i < 3; i++) { - MSG_WriteCoord (&sv.signon, - ((entity_state_t*)svent->data)->origin[i]); - MSG_WriteAngle (&sv.signon, - ((entity_state_t*)svent->data)->angles[i]); - } + NET_SVC_SpawnBaseline_Emit (&block, &sv.signon); } } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 77640cab6..190f5f70c 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -76,6 +76,7 @@ static const char rcsid[] = #include "crudefile.h" #include "game.h" #include "net.h" +#include "net_svc.h" #include "pmove.h" #include "server.h" #include "sv_progs.h" @@ -260,11 +261,14 @@ SV_FinalMessage (const char *message) { client_t *cl; int i; + net_svc_print_t block; + + block.level = PRINT_HIGH; + block.message = message; SZ_Clear (net_message->message); MSG_WriteByte (net_message->message, svc_print); - MSG_WriteByte (net_message->message, PRINT_HIGH); - MSG_WriteString (net_message->message, message); + NET_SVC_Print_Emit (&block, net_message->message); MSG_WriteByte (net_message->message, svc_disconnect); for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) @@ -369,6 +373,7 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf) { char *info; int i; + net_svc_updateuserinfo_t block; i = client - svs.clients; @@ -393,10 +398,11 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf) info = client->userinfo ? Info_MakeString (client->userinfo, make_info_string_filter) : ""; + block.slot = i; + block.userid = client->userid; + block.userinfo = info; MSG_WriteByte (buf, svc_updateuserinfo); - MSG_WriteByte (buf, i); - MSG_WriteLong (buf, client->userid); - MSG_WriteString (buf, info); + NET_SVC_UpdateUserInfo_Emit (&block, buf); } /* @@ -2171,6 +2177,7 @@ Master_Shutdown (void) static inline qboolean iswhitespace (char c) { + c &= 127; return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } @@ -2200,9 +2207,9 @@ SV_ExtractFromUserinfo (client_t *cl) for (r = newname; *p && r != newname + sizeof (newname) - 1; p++) { if (iswhitespace (*p)) { if (!iswhitespace (p[1]) && p[1] != '\0') - *r++ = *p; + *r++ = ' '; // get rid of any special chars } else - *r++ = *p; + *r++ = *p & 127; // get rid of bold } *r = '\0'; @@ -2210,6 +2217,14 @@ SV_ExtractFromUserinfo (client_t *cl) if (!*newname) badname = true; + // ':' is used in chat messages + if (strchr (newname, ':')) + badname = true; + + // I dunno if this is possible, but better safe than sorry + if (strchr (newname, '"')) + badname = true; + // impersonating an user-xxx name. if they're using it // legitimately it'll be a no-op later on if (!strncasecmp (newname, "user-", 5)) @@ -2268,9 +2283,10 @@ SV_ExtractFromUserinfo (client_t *cl) } } - // finally, report it to all our friends + // finally, report it to all our friends, but only if more + // than whitespace changed // if (cl->state >= cs_spawned && !cl->spectator) - if (*cl->name) + if (*cl->name && strcmp (cl->name, newname)) SV_BroadcastPrintf (PRINT_HIGH, "%s changed name to %s\n", cl->name, newname); strcpy (cl->name, newname); diff --git a/qw/source/sv_model.c b/qw/source/sv_model.c index 2f62c1d6c..08a3998c4 100644 --- a/qw/source/sv_model.c +++ b/qw/source/sv_model.c @@ -36,7 +36,6 @@ static const char rcsid[] = #include "QF/model.h" const int mod_lightmap_bytes = 1; -cvar_t *gl_sky_divide; // not used but needed for linking void Mod_LoadBrushModel (model_t *mod, void *buffer); diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index b39597af2..65da83a40 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -607,14 +607,14 @@ SV_CheckWaterTransition (edict_t *ent) if (cont <= CONTENTS_WATER) { if (SVfloat (ent, watertype) == CONTENTS_EMPTY) { // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + SV_StartSound (ent, 0, "misc/h2ohit1.wav", 1, 1); } SVfloat (ent, watertype) = cont; SVfloat (ent, waterlevel) = 1; } else { if (SVfloat (ent, watertype) != CONTENTS_EMPTY) { // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + SV_StartSound (ent, 0, "misc/h2ohit1.wav", 1, 1); } SVfloat (ent, watertype) = CONTENTS_EMPTY; SVfloat (ent, waterlevel) = cont; @@ -717,7 +717,7 @@ SV_Physics_Step (edict_t *ent) if ((int) SVfloat (ent, flags) & FL_ONGROUND) // just hit ground { if (hitsound) - SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + SV_StartSound (ent, 0, "demon/dland2.wav", 1, 1); } } // regular thinking diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index a1b7d4955..af1633972 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -45,6 +45,7 @@ static const char rcsid[] = #include "compat.h" #include "crudefile.h" +#include "net_svc.h" #include "server.h" #include "sv_pr_cmds.h" #include "sv_progs.h" @@ -279,17 +280,16 @@ PF_ambientsound (progs_t *pr) { const char **check; const char *samp; - float *pos; - float vol, attenuation; - int i, soundnum; + net_svc_spawnstaticsound_t block; - pos = G_VECTOR (pr, OFS_PARM0); + VectorCopy (G_VECTOR (pr, OFS_PARM0), block.position); samp = G_STRING (pr, OFS_PARM1); - vol = G_FLOAT (pr, OFS_PARM2); - attenuation = G_FLOAT (pr, OFS_PARM3); + block.volume = G_FLOAT (pr, OFS_PARM2) * 255; + block.attenuation = G_FLOAT (pr, OFS_PARM3) * 64; // check to see if samp was properly precached - for (soundnum = 0, check = sv.sound_precache; *check; check++, soundnum++) + for (block.sound_num = 0, check = sv.sound_precache; *check; + check++, block.sound_num++) if (!strcmp (*check, samp)) break; @@ -300,14 +300,7 @@ PF_ambientsound (progs_t *pr) // add an svc_spawnambient command to the level signon packet MSG_WriteByte (&sv.signon, svc_spawnstaticsound); - for (i = 0; i < 3; i++) - MSG_WriteCoord (&sv.signon, pos[i]); - - MSG_WriteByte (&sv.signon, soundnum); - - MSG_WriteByte (&sv.signon, vol * 255); - MSG_WriteByte (&sv.signon, attenuation * 64); - + NET_SVC_SpawnStaticSound_Emit (&block, &sv.signon); } /* @@ -327,13 +320,13 @@ PF_sound (progs_t *pr) { const char *sample; edict_t *entity; - float attenuation; - int channel, volume; + float volume, attenuation; + int channel; entity = G_EDICT (pr, OFS_PARM0); channel = G_FLOAT (pr, OFS_PARM1); sample = G_STRING (pr, OFS_PARM2); - volume = G_FLOAT (pr, OFS_PARM3) * 255; + volume = G_FLOAT (pr, OFS_PARM3); attenuation = G_FLOAT (pr, OFS_PARM4); SV_StartSound (entity, channel, sample, volume, attenuation); @@ -1142,25 +1135,21 @@ int SV_ModelIndex (const char *name); void PF_makestatic (progs_t *pr) { - const char *model; edict_t *ent; - int i; + net_svc_spawnstatic_t block; ent = G_EDICT (pr, OFS_PARM0); - MSG_WriteByte (&sv.signon, svc_spawnstatic); - - model = PR_GetString (pr, SVstring (ent, model)); // SV_Printf ("Model: %d %s\n", SVstring (ent, model), model); - MSG_WriteByte (&sv.signon, SV_ModelIndex (model)); + block.modelindex = SV_ModelIndex (PR_GetString (pr, SVstring (ent, model))); + block.frame = SVfloat (ent, frame); + block.colormap = SVfloat (ent, colormap); + block.skinnum = SVfloat (ent, skin); + VectorCopy (SVvector (ent, origin), block.origin); + VectorCopy (SVvector (ent, angles), block.angles); - MSG_WriteByte (&sv.signon, SVfloat (ent, frame)); - MSG_WriteByte (&sv.signon, SVfloat (ent, colormap)); - MSG_WriteByte (&sv.signon, SVfloat (ent, skin)); - for (i = 0; i < 3; i++) { - MSG_WriteCoord (&sv.signon, SVvector (ent, origin)[i]); - MSG_WriteAngle (&sv.signon, SVvector (ent, angles)[i]); - } + MSG_WriteByte (&sv.signon, svc_spawnstatic); + NET_SVC_SpawnStatic_Emit (&block, &sv.signon); // throw the entity away now ED_Free (pr, ent); @@ -1369,6 +1358,7 @@ PF_setinfokey (progs_t *pr) int e1 = NUM_FOR_EDICT (pr, edict); const char *key = G_STRING (pr, OFS_PARM1); const char *value = G_STRING (pr, OFS_PARM2); + net_svc_setinfo_t block; if (e1 == 0) { if (*value) @@ -1382,12 +1372,11 @@ PF_setinfokey (progs_t *pr) SV_ExtractFromUserinfo (&svs.clients[e1 - 1]); if (Info_FilterForKey (key, client_info_filters)) { + block.slot = e1 - 1; + block.key = key; + block.value = Info_ValueForKey (svs.clients[e1 - 1].userinfo, key); MSG_WriteByte (&sv.reliable_datagram, svc_setinfo); - MSG_WriteByte (&sv.reliable_datagram, e1 - 1); - MSG_WriteString (&sv.reliable_datagram, key); - MSG_WriteString (&sv.reliable_datagram, - Info_ValueForKey (svs.clients[e1 - 1].userinfo, - key)); + NET_SVC_SetInfo_Emit (&block, &sv.reliable_datagram); } } } diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 9c4c7bb5c..05242ead8 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -49,6 +49,7 @@ static const char rcsid[] = #include "bothdefs.h" #include "compat.h" +#include "net_svc.h" #include "server.h" #include "sv_progs.h" @@ -69,6 +70,7 @@ void SV_FlushRedirect (void) { char send[8000 + 6]; + net_svc_print_t block; if (sv_redirected == RD_PACKET) { send[0] = 0xff; @@ -80,10 +82,15 @@ SV_FlushRedirect (void) NET_SendPacket (strlen (send) + 1, send, net_from); } else if (sv_redirected == RD_CLIENT) { + block.level = PRINT_HIGH; + block.message = outputbuf; ClientReliableWrite_Begin (host_client, svc_print, strlen (outputbuf) + 3); - ClientReliableWrite_Byte (host_client, PRINT_HIGH); - ClientReliableWrite_String (host_client, outputbuf); + if (host_client->num_backbuf) { + NET_SVC_Print_Emit (&block, &host_client->backbuf); + ClientReliable_FinishWrite (host_client); + } else + NET_SVC_Print_Emit (&block, &host_client->netchan.message); } // clear it outputbuf[0] = 0; @@ -220,6 +227,7 @@ SV_PrintToClient (client_t *cl, int level, const char *string) unsigned char *b; int size; static int buffer_size; + net_svc_print_t block; size = strlen (string) + 1; if (size > buffer_size) { @@ -239,9 +247,14 @@ SV_PrintToClient (client_t *cl, int level, const char *string) if (*b != 0xFF) b++; + block.level = level; + block.message = buffer; ClientReliableWrite_Begin (cl, svc_print, strlen (buffer) + 3); - ClientReliableWrite_Byte (cl, level); - ClientReliableWrite_String (cl, buffer); + if (cl->num_backbuf) { + NET_SVC_Print_Emit (&block, &cl->backbuf); + ClientReliable_FinishWrite (cl); + } else + NET_SVC_Print_Emit (&block, &cl->netchan.message); } /* @@ -416,16 +429,16 @@ SV_Multicast (vec3_t origin, int to) Larger attenuations will drop off. (max 4 attenuation) */ void -SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, - float attenuation) +SV_StartSound (edict_t *entity, int channel, const char *sample, + float volume, float attenuation) { - int ent, field_mask, sound_num, i; + int i, sound_num; qboolean use_phs; qboolean reliable = false; - vec3_t origin; + net_svc_sound_t block; - if (volume < 0 || volume > 255) - SV_Error ("SV_StartSound: volume = %i", volume); + if (volume < 0 || volume > 1) + SV_Error ("SV_StartSound: volume = %f", volume); if (attenuation < 0 || attenuation > 4) SV_Error ("SV_StartSound: attenuation = %f", attenuation); @@ -444,7 +457,9 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, return; } - ent = NUM_FOR_EDICT (&sv_pr_state, entity); + block.sound_num = sound_num; + + block.entity = NUM_FOR_EDICT (&sv_pr_state, entity); if ((channel & 8) || !sv_phs->int_val) // no PHS flag { @@ -459,37 +474,34 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, // if (channel == CHAN_BODY || channel == CHAN_VOICE) // reliable = true; - channel = (ent << 3) | channel; + block.channel = channel; - field_mask = 0; - if (volume != DEFAULT_SOUND_PACKET_VOLUME) - channel |= SND_VOLUME; - if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION) - channel |= SND_ATTENUATION; + block.volume = volume; + // 4 * 64 == 256, which overflows a byte. 4 is the stated max for + // it, and I don't want to break any progs, so I just nudge it + // down instead + if (attenuation == 4) + attenuation = 3.999; + block.attenuation = attenuation; // use the entity origin unless it is a bmodel if (SVfloat (entity, solid) == SOLID_BSP) { for (i = 0; i < 3; i++) - origin[i] = SVvector (entity, origin)[i] + 0.5 * + block.position[i] = SVvector (entity, origin)[i] + 0.5 * (SVvector (entity, mins)[i] + SVvector (entity, maxs)[i]); } else { - VectorCopy (SVvector (entity, origin), origin); + VectorCopy (SVvector (entity, origin), block.position); } MSG_WriteByte (&sv.multicast, svc_sound); - MSG_WriteShort (&sv.multicast, channel); - if (channel & SND_VOLUME) - MSG_WriteByte (&sv.multicast, volume); - if (channel & SND_ATTENUATION) - MSG_WriteByte (&sv.multicast, attenuation * 64); - MSG_WriteByte (&sv.multicast, sound_num); - for (i = 0; i < 3; i++) - MSG_WriteCoord (&sv.multicast, origin[i]); + NET_SVC_Sound_Emit (&block, &sv.multicast); if (use_phs) - SV_Multicast (origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS); + SV_Multicast (block.position, + reliable ? MULTICAST_PHS_R : MULTICAST_PHS); else - SV_Multicast (origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL); + SV_Multicast (block.position, + reliable ? MULTICAST_ALL_R : MULTICAST_ALL); } /* FRAME UPDATES */ @@ -522,6 +534,7 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) { edict_t *ent, *other; int i; + net_svc_damage_t block; ent = client->edict; @@ -534,13 +547,14 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) // send a damage message if the player got hit this frame if (SVfloat (ent, dmg_take) || SVfloat (ent, dmg_save)) { other = PROG_TO_EDICT (&sv_pr_state, SVentity (ent, dmg_inflictor)); - MSG_WriteByte (msg, svc_damage); - MSG_WriteByte (msg, SVfloat (ent, dmg_save)); - MSG_WriteByte (msg, SVfloat (ent, dmg_take)); + block.armor = SVfloat (ent, dmg_save); + block.blood = SVfloat (ent, dmg_take); for (i = 0; i < 3; i++) - MSG_WriteCoord (msg, SVvector (other, origin)[i] + 0.5 * + block.from[i] = SVvector (other, origin)[i] + 0.5 * (SVvector (other, mins)[i] + - SVvector (other, maxs)[i])); + SVvector (other, maxs)[i]); + MSG_WriteByte (msg, svc_damage); + NET_SVC_Damage_Emit (&block, msg); SVfloat (ent, dmg_take) = 0; SVfloat (ent, dmg_save) = 0; @@ -780,7 +794,6 @@ SV_SendClientMessages (void) // if the reliable message overflowed, drop the client if (c->netchan.message.overflowed) { int i; - extern void Analyze_Server_Packet (byte *data, int len); byte *data = Hunk_TempAlloc (MAX_MSGLEN + 8); memset (data, 0, 8); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index e2546c1ee..999d3178c 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -54,6 +54,7 @@ static const char rcsid[] = #include "compat.h" #include "bothdefs.h" #include "msg_ucmd.h" +#include "net_svc.h" #include "pmove.h" #include "server.h" #include "sv_progs.h" @@ -96,7 +97,7 @@ void SV_New_f (void) { const char *gamedir; - int playernum; + net_svc_serverdata_t block; if (host_client->state == cs_spawned) return; @@ -115,37 +116,23 @@ SV_New_f (void) //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow if (host_client->num_backbuf) { - SV_Printf ("WARNING %s: [SV_New] Back buffered (%d0, clearing\n", + SV_Printf ("WARNING %s: [SV_New] Back buffered (%d), clearing\n", host_client->name, host_client->netchan.message.cursize); host_client->num_backbuf = 0; SZ_Clear (&host_client->netchan.message); } + // send the serverdata + block.protocolversion = PROTOCOL_VERSION; + block.servercount = svs.spawncount; + block.gamedir = gamedir; + block.playernum = NUM_FOR_EDICT (&sv_pr_state, host_client->edict) - 1; + block.spectator = host_client->spectator; + block.levelname = PR_GetString (&sv_pr_state, + SVstring (sv.edicts, message)); + block.movevars = movevars; MSG_WriteByte (&host_client->netchan.message, svc_serverdata); - MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION); - MSG_WriteLong (&host_client->netchan.message, svs.spawncount); - MSG_WriteString (&host_client->netchan.message, gamedir); - - playernum = NUM_FOR_EDICT (&sv_pr_state, host_client->edict) - 1; - if (host_client->spectator) - playernum |= 128; - MSG_WriteByte (&host_client->netchan.message, playernum); - - // send full levelname - MSG_WriteString (&host_client->netchan.message, - PR_GetString (&sv_pr_state, SVstring (sv.edicts, message))); - - // send the movevars - MSG_WriteFloat (&host_client->netchan.message, movevars.gravity); - MSG_WriteFloat (&host_client->netchan.message, movevars.stopspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.maxspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.spectatormaxspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.accelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.airaccelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.wateraccelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.friction); - MSG_WriteFloat (&host_client->netchan.message, movevars.waterfriction); - MSG_WriteFloat (&host_client->netchan.message, movevars.entgravity); + NET_SVC_ServerData_Emit (&block, &host_client->netchan.message); // send music MSG_WriteByte (&host_client->netchan.message, svc_cdtrack); @@ -165,12 +152,14 @@ void SV_Soundlist_f (void) { const char **s; - unsigned n; + int i, size; + net_svc_soundlist_t block; if (host_client->state != cs_connected) { SV_Printf ("soundlist not valid -- already spawned\n"); return; } + // handle the case of a level changing while a client was connecting if (atoi (Cmd_Argv (1)) != svs.spawncount) { SV_Printf ("SV_Soundlist_f from different level\n"); @@ -178,34 +167,40 @@ SV_Soundlist_f (void) return; } - n = atoi (Cmd_Argv (2)); - if (n >= MAX_SOUNDS) { + block.startsound = atoi (Cmd_Argv (2)); + if (block.startsound >= MAX_SOUNDS) { SV_Printf ("SV_Soundlist_f: Invalid soundlist index\n"); SV_New_f (); return; } -//NOTE: This doesn't go through ClientReliableWrite since it's before the user -//spawns. These functions are written to not overflow + + // NOTE: This doesn't go through ClientReliableWrite since it's + // before the user spawns. These functions are written to not + // overflow if (host_client->num_backbuf) { - SV_Printf ("WARNING %s: [SV_Soundlist] Back buffered (%d0, clearing", + SV_Printf ("WARNING %s: [SV_Soundlist] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); host_client->num_backbuf = 0; SZ_Clear (&host_client->netchan.message); } - MSG_WriteByte (&host_client->netchan.message, svc_soundlist); - MSG_WriteByte (&host_client->netchan.message, n); - for (s = sv.sound_precache + 1 + n; - *s && host_client->netchan.message.cursize < (MAX_MSGLEN / 2); - s++, n++) MSG_WriteString (&host_client->netchan.message, *s); - - MSG_WriteByte (&host_client->netchan.message, 0); + for (s = sv.sound_precache + 1 + block.startsound, i = 0, size = 0; + *s; i++, s++) { + if (host_client->netchan.message.cursize + size >= (MAX_MSGLEN / 2)) + break; + size += strlen (*s) + 1; + block.sounds[i] = *s; + } + block.sounds[i] = ""; // next msg if (*s) - MSG_WriteByte (&host_client->netchan.message, n); + block.nextsound = block.startsound + i; else - MSG_WriteByte (&host_client->netchan.message, 0); + block.nextsound = 0; + + MSG_WriteByte (&host_client->netchan.message, svc_soundlist); + NET_SVC_Soundlist_Emit (&block, &host_client->netchan.message); } /* @@ -215,12 +210,14 @@ void SV_Modellist_f (void) { const char **s; - unsigned n; + int i, size; + net_svc_modellist_t block; if (host_client->state != cs_connected) { SV_Printf ("modellist not valid -- already spawned\n"); return; } + // handle the case of a level changing while a client was connecting if (atoi (Cmd_Argv (1)) != svs.spawncount) { SV_Printf ("SV_Modellist_f from different level\n"); @@ -228,33 +225,40 @@ SV_Modellist_f (void) return; } - n = atoi (Cmd_Argv (2)); - if (n >= MAX_MODELS) { + block.startmodel = atoi (Cmd_Argv (2)); + if (block.startmodel >= MAX_MODELS) { SV_Printf ("SV_Modellist_f: Invalid modellist index\n"); SV_New_f (); return; } -//NOTE: This doesn't go through ClientReliableWrite since it's before the user -//spawns. These functions are written to not overflow + + // NOTE: This doesn't go through ClientReliableWrite since it's + // before the user spawns. These functions are written to not + // overflow if (host_client->num_backbuf) { - SV_Printf ("WARNING %s: [SV_Modellist] Back buffered (%d0, clearing", + SV_Printf ("WARNING %s: [SV_Modellist] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); host_client->num_backbuf = 0; SZ_Clear (&host_client->netchan.message); } - MSG_WriteByte (&host_client->netchan.message, svc_modellist); - MSG_WriteByte (&host_client->netchan.message, n); - for (s = sv.model_precache + 1 + n; - *s && host_client->netchan.message.cursize < (MAX_MSGLEN / 2); - s++, n++) MSG_WriteString (&host_client->netchan.message, *s); - MSG_WriteByte (&host_client->netchan.message, 0); + for (s = sv.model_precache + 1 + block.startmodel, i = 0, size = 0; + *s; i++, s++) { + if (host_client->netchan.message.cursize + size >= (MAX_MSGLEN / 2)) + break; + size += strlen (*s) + 1; + block.models[i] = *s; + } + block.models[i] = ""; // next msg if (*s) - MSG_WriteByte (&host_client->netchan.message, n); + block.nextmodel = block.startmodel + i; else - MSG_WriteByte (&host_client->netchan.message, 0); + block.nextmodel = 0; + + MSG_WriteByte (&host_client->netchan.message, svc_modellist); + NET_SVC_Modellist_Emit (&block, &host_client->netchan.message); } /* @@ -562,27 +566,27 @@ void SV_NextDownload_f (void) { byte buffer[1024]; - int r; - int percent; - int size; + net_svc_download_t block; if (!host_client->download) return; - r = host_client->downloadsize - host_client->downloadcount; - if (r > 768) - r = 768; - r = Qread (host_client->download, buffer, r); - ClientReliableWrite_Begin (host_client, svc_download, 6 + r); - ClientReliableWrite_Short (host_client, r); + block.size = host_client->downloadsize - host_client->downloadcount; + if (block.size > 768) + block.size = 768; + block.size = Qread (host_client->download, buffer, block.size); - host_client->downloadcount += r; - size = host_client->downloadsize; - if (!size) - size = 1; - percent = host_client->downloadcount * 100 / size; - ClientReliableWrite_Byte (host_client, percent); - ClientReliableWrite_SZ (host_client, buffer, r); + host_client->downloadcount += block.size; + block.percent = host_client->downloadcount * 100 / + (host_client->downloadsize ?: 1); + + block.data = buffer; + ClientReliableWrite_Begin (host_client, svc_download, 6 + block.size); + if (host_client->num_backbuf) { + NET_SVC_Download_Emit (&block, &host_client->backbuf); + ClientReliable_FinishWrite (host_client); + } else + NET_SVC_Download_Emit (&block, &host_client->netchan.message); if (host_client->downloadcount != host_client->downloadsize) return; @@ -691,6 +695,7 @@ SV_BeginDownload_f (void) int size; char realname[MAX_OSPATH]; int zip; + net_svc_download_t block; name = Cmd_Argv (1); // hacked by zoid to allow more conrol over download @@ -708,9 +713,14 @@ SV_BeginDownload_f (void) || (strncmp (name, "maps/", 5) == 0 && !allow_download_maps->int_val) // MUST be in a subdirectory || !strstr (name, "/")) { // don't allow anything with .. path + block.size = -1; + block.percent = 0; ClientReliableWrite_Begin (host_client, svc_download, 4); - ClientReliableWrite_Short (host_client, -1); - ClientReliableWrite_Byte (host_client, 0); + if (host_client->num_backbuf) { + NET_SVC_Download_Emit (&block, &host_client->backbuf); + ClientReliable_FinishWrite (host_client); + } else + NET_SVC_Download_Emit (&block, &host_client->netchan.message); return; } @@ -746,19 +756,30 @@ SV_BeginDownload_f (void) } SV_Printf ("Couldn't download %s to %s\n", name, host_client->name); + + block.size = -1; + block.percent = 0; ClientReliableWrite_Begin (host_client, svc_download, 4); - ClientReliableWrite_Short (host_client, -1); - ClientReliableWrite_Byte (host_client, 0); + if (host_client->num_backbuf) { + NET_SVC_Download_Emit (&block, &host_client->backbuf); + ClientReliable_FinishWrite (host_client); + } else + NET_SVC_Download_Emit (&block, &host_client->netchan.message); return; } if (zip && strcmp (realname, name)) { SV_Printf ("download renamed to %s\n", realname); + + block.size = -2; + block.percent = 0; + block.name = realname; ClientReliableWrite_Begin (host_client, svc_download, strlen (realname) + 5); - ClientReliableWrite_Short (host_client, -2); - ClientReliableWrite_Byte (host_client, 0); - ClientReliableWrite_String (host_client, realname); + if (host_client->num_backbuf) + NET_SVC_Download_Emit (&block, &host_client->backbuf); + else + NET_SVC_Download_Emit (&block, &host_client->netchan.message); ClientReliable_FinishWrite (host_client); } @@ -1115,6 +1136,8 @@ SV_Msg_f (void) void SV_SetInfo_f (void) { + net_svc_setinfo_t block; + if (Cmd_Argc () == 1) { SV_Printf ("User info settings:\n"); Info_Print (host_client->userinfo); @@ -1153,12 +1176,11 @@ SV_SetInfo_f (void) SV_ExtractFromUserinfo (host_client); if (Info_FilterForKey (Cmd_Argv (1), client_info_filters)) { + block.slot = host_client - svs.clients; + block.key = Cmd_Argv (1); + block.value = Info_ValueForKey (host_client->userinfo, Cmd_Argv (1)); MSG_WriteByte (&sv.reliable_datagram, svc_setinfo); - MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); - MSG_WriteString (&sv.reliable_datagram, Cmd_Argv (1)); - MSG_WriteString (&sv.reliable_datagram, - Info_ValueForKey (host_client->userinfo, - Cmd_Argv (1))); + NET_SVC_SetInfo_Emit (&block, &sv.reliable_datagram); } } @@ -1817,7 +1839,7 @@ SV_UserInit (void) "Toggles the ability of spectators to talk to players"); sv_mapcheck = Cvar_Get ("sv_mapcheck", "1", CVAR_NONE, NULL, "Toggle the use of map checksumming to check for players who edit maps to cheat"); - sv_kickfake = Cvar_Get ("sv_kickfake", "1", CVAR_NONE, NULL, + sv_kickfake = Cvar_Get ("sv_kickfake", "0", CVAR_NONE, NULL, "Kick users sending to send fake talk messages"); }