From: Cloudwalk Date: Tue, 22 Sep 2020 02:34:48 +0000 (-0400) Subject: Initial commit of protocol redesign X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=b47c683dbb0d68853ae23581df5e132c2eb689ba;p=xonotic%2Fdarkplaces.git Initial commit of protocol redesign The Quake protocol family is now implemented on a per-struct basis using the new protocol_t struct. It's a container for protocol info such as name, number, and soon max edicts, max models, max frames, max sounds, etc. For now, it also contains function pointers to MSG_ functions. The MSG_ functions (specifically the Read and WriteCoord, Angle, Vector functions have been made generic, and these function pointers point to them instead of using protocol-based branching. The protocol net messages themselves are now a jump table, not unlike the QC builtins interface. This will make things cleaner and scalable for implementing Quake protocols that might be dramatically different from NQ and QW. --- diff --git a/cl_cmd.c b/cl_cmd.c index 569ba834..c7918be1 100644 --- a/cl_cmd.c +++ b/cl_cmd.c @@ -64,8 +64,8 @@ void CL_ForwardToServer (const char *s) // LadyHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my // attention, it has been eradicated from here, its only (former) use in // all of darkplaces. - if (cls.protocol == PROTOCOL_QUAKEWORLD) - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + if (cls.protocol == &protocol_quakeworld) + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); else MSG_WriteByte(&cls.netcon->message, clc_stringcmd); if ((!strncmp(s, "say ", 4) || !strncmp(s, "say_team ", 9)) && cl_locs_enable.integer) diff --git a/cl_demo.c b/cl_demo.c index 7c787432..337feeb5 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -443,7 +443,7 @@ void CL_PlayDemo_f(cmd_state_t *cmd) // update networking ports (this is mainly just needed at startup) NetConn_UpdateSockets(); - cls.protocol = PROTOCOL_QUAKE; + cls.protocol = &protocol_netquake; Con_Printf("Playing demo %s.\n", name); cls.demofile = f; diff --git a/cl_ents.c b/cl_ents.c index b5e93f61..11fd2a59 100644 --- a/cl_ents.c +++ b/cl_ents.c @@ -20,7 +20,7 @@ int EntityState_ReadExtendBits(void) void EntityState_ReadFields(entity_state_t *e, unsigned int bits) { - if (cls.protocol == PROTOCOL_DARKPLACES2) + if (cls.protocol == &protocol_dpp2) { if (bits & E_ORIGIN1) e->origin[0] = MSG_ReadCoord16i(&cl_message); @@ -52,7 +52,7 @@ void EntityState_ReadFields(entity_state_t *e, unsigned int bits) e->origin[2] = MSG_ReadCoord32f(&cl_message); } } - if ((cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6) && !(e->flags & RENDER_LOWPRECISION)) + if ((cls.protocol == &protocol_dpp5 || cls.protocol == &protocol_dpp6) && !(e->flags & RENDER_LOWPRECISION)) { if (bits & E_ANGLE1) e->angles[0] = MSG_ReadAngle16i(&cl_message); @@ -94,7 +94,7 @@ void EntityState_ReadFields(entity_state_t *e, unsigned int bits) e->glowsize = MSG_ReadByte(&cl_message); if (bits & E_GLOWCOLOR) e->glowcolor = MSG_ReadByte(&cl_message); - if (cls.protocol == PROTOCOL_DARKPLACES2) + if (cls.protocol == &protocol_dpp2) if (bits & E_FLAGS) e->flags = MSG_ReadByte(&cl_message); if (bits & E_TAGATTACHMENT) diff --git a/cl_ents5.c b/cl_ents5.c index d245e8a2..08b0409c 100644 --- a/cl_ents5.c +++ b/cl_ents5.c @@ -294,7 +294,7 @@ void EntityFrame5_CL_ReadFrame(void) // read the number of this frame to echo back in next input packet framenum = MSG_ReadLong(&cl_message); CL_NewFrameReceived(framenum); - if (cls.protocol != PROTOCOL_QUAKE && cls.protocol != PROTOCOL_QUAKEDP && cls.protocol != PROTOCOL_NEHAHRAMOVIE && cls.protocol != PROTOCOL_DARKPLACES1 && cls.protocol != PROTOCOL_DARKPLACES2 && cls.protocol != PROTOCOL_DARKPLACES3 && cls.protocol != PROTOCOL_DARKPLACES4 && cls.protocol != PROTOCOL_DARKPLACES5 && cls.protocol != PROTOCOL_DARKPLACES6) + if (cls.protocol != &protocol_netquake && cls.protocol != &protocol_quakedp && cls.protocol != &protocol_nehahramovie && cls.protocol != &protocol_dpp1 && cls.protocol != &protocol_dpp2 && cls.protocol != &protocol_dpp3 && cls.protocol != &protocol_dpp4 && cls.protocol != &protocol_dpp5 && cls.protocol != &protocol_dpp6) cls.servermovesequence = MSG_ReadLong(&cl_message); // read entity numbers until we find a 0x8000 // (which would be remove world entity, but is actually a terminator) diff --git a/cl_ents_nq.c b/cl_ents_nq.c index 0edd34e3..3d1b1752 100644 --- a/cl_ents_nq.c +++ b/cl_ents_nq.c @@ -9,7 +9,7 @@ void EntityFrameQuake_ReadEntity(int bits) if (bits & U_MOREBITS) bits |= (MSG_ReadByte(&cl_message)<<8); - if ((bits & U_EXTEND1) && cls.protocol != PROTOCOL_NEHAHRAMOVIE) + if ((bits & U_EXTEND1) && cls.protocol != &protocol_nehahramovie) { bits |= MSG_ReadByte(&cl_message) << 16; if (bits & U_EXTEND2) @@ -54,7 +54,7 @@ void EntityFrameQuake_ReadEntity(int bits) s.flags = 0; if (bits & U_MODEL) { - if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3) + if (cls.protocol == &protocol_nehahrabjp || cls.protocol == &protocol_nehahrabjp2 || cls.protocol == &protocol_nehahrabjp3) s.modelindex = (unsigned short) MSG_ReadShort(&cl_message); else s.modelindex = (s.modelindex & 0xFF00) | MSG_ReadByte(&cl_message); @@ -63,12 +63,12 @@ void EntityFrameQuake_ReadEntity(int bits) if (bits & U_COLORMAP) s.colormap = MSG_ReadByte(&cl_message); if (bits & U_SKIN) s.skin = MSG_ReadByte(&cl_message); if (bits & U_EFFECTS) s.effects = (s.effects & 0xFF00) | MSG_ReadByte(&cl_message); - if (bits & U_ORIGIN1) s.origin[0] = MSG_ReadCoord(&cl_message, cls.protocol); - if (bits & U_ANGLE1) s.angles[0] = MSG_ReadAngle(&cl_message, cls.protocol); - if (bits & U_ORIGIN2) s.origin[1] = MSG_ReadCoord(&cl_message, cls.protocol); - if (bits & U_ANGLE2) s.angles[1] = MSG_ReadAngle(&cl_message, cls.protocol); - if (bits & U_ORIGIN3) s.origin[2] = MSG_ReadCoord(&cl_message, cls.protocol); - if (bits & U_ANGLE3) s.angles[2] = MSG_ReadAngle(&cl_message, cls.protocol); + if (bits & U_ORIGIN1) s.origin[0] = cls.protocol->ReadCoord(&cl_message); + if (bits & U_ANGLE1) s.angles[0] = cls.protocol->ReadAngle(&cl_message); + if (bits & U_ORIGIN2) s.origin[1] = cls.protocol->ReadCoord(&cl_message); + if (bits & U_ANGLE2) s.angles[1] = cls.protocol->ReadAngle(&cl_message); + if (bits & U_ORIGIN3) s.origin[2] = cls.protocol->ReadCoord(&cl_message); + if (bits & U_ANGLE3) s.angles[2] = cls.protocol->ReadAngle(&cl_message); if (bits & U_STEP) s.flags |= RENDER_STEP; if (bits & U_ALPHA) s.alpha = MSG_ReadByte(&cl_message); if (bits & U_SCALE) s.scale = MSG_ReadByte(&cl_message); @@ -83,7 +83,7 @@ void EntityFrameQuake_ReadEntity(int bits) if (bits & U_EXTERIORMODEL) s.flags |= RENDER_EXTERIORMODEL; // LadyHavoc: to allow playback of the Nehahra movie - if (cls.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1)) + if (cls.protocol == &protocol_nehahramovie && (bits & U_EXTEND1)) { // LadyHavoc: evil format int i = (int)MSG_ReadFloat(&cl_message); diff --git a/cl_ents_qw.c b/cl_ents_qw.c index dcbe7490..553870f4 100644 --- a/cl_ents_qw.c +++ b/cl_ents_qw.c @@ -67,7 +67,7 @@ void EntityStateQW_ReadPlayerUpdate(void) s->number = enumber; s->colormap = enumber; playerflags = MSG_ReadShort(&cl_message); - MSG_ReadVector(&cl_message, s->origin, cls.protocol); + cls.protocol->ReadVector(&cl_message, s->origin); s->frame = MSG_ReadByte(&cl_message); VectorClear(viewangles); diff --git a/cl_input.c b/cl_input.c index ebde4ed7..8c812018 100644 --- a/cl_input.c +++ b/cl_input.c @@ -1059,7 +1059,7 @@ static void CL_ClientMovement_Physics_Swim(cl_clientmovement_state_t *s) if (s->waterjumptime <= 0) { // water friction - f = 1 - s->cmd.frametime * cl.movevars_waterfriction * (cls.protocol == PROTOCOL_QUAKEWORLD ? s->waterlevel : 1); + f = 1 - s->cmd.frametime * cl.movevars_waterfriction * (cls.protocol == &protocol_quakeworld ? s->waterlevel : 1); f = bound(0, f, 1); VectorScale(s->velocity, f, s->velocity); @@ -1359,7 +1359,7 @@ static void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) // this mimics it for compatibility VectorSet(neworigin2, s->origin[0] + s->velocity[0]*(16/f), s->origin[1] + s->velocity[1]*(16/f), s->origin[2] + s->mins[2]); VectorSet(neworigin3, neworigin2[0], neworigin2[1], neworigin2[2] - 34); - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) trace = CL_TraceBox(neworigin2, s->mins, s->maxs, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true); else trace = CL_TraceLine(neworigin2, neworigin3, MOVE_NORMAL, s->self, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP, 0, 0, collision_extendmovelength.value, true, true, NULL, true, false); @@ -1385,7 +1385,7 @@ static void CL_ClientMovement_Physics_Walk(cl_clientmovement_state_t *s) else s->velocity[2] -= gravity; } - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) s->velocity[2] = 0; if (VectorLength2(s->velocity)) CL_ClientMovement_Move(s); @@ -1473,7 +1473,7 @@ static void CL_ClientMovement_PlayerMove(cl_clientmovement_state_t *s) extern cvar_t host_timescale; void CL_UpdateMoveVars(void) { - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { cl.moveflags = 0; } @@ -1820,7 +1820,7 @@ void CL_SendMove(void) cl.cmd.msec = 100; cl.cmd.frametime = cl.cmd.msec * (1.0 / 1000.0); - switch(cls.protocol) + switch(cls.protocol->num) { case PROTOCOL_QUAKEWORLD: // quakeworld uses a different cvar with opposite meaning, for compatibility @@ -1842,11 +1842,10 @@ void CL_SendMove(void) cl.cmd.jump = (cl.cmd.buttons & 2) != 0; cl.cmd.crouch = 0; - switch (cls.protocol) + switch (cls.protocol->num) { case PROTOCOL_QUAKEWORLD: case PROTOCOL_QUAKE: - case PROTOCOL_QUAKEDP: case PROTOCOL_NEHAHRAMOVIE: case PROTOCOL_NEHAHRABJP: case PROTOCOL_NEHAHRABJP2: @@ -1886,7 +1885,7 @@ void CL_SendMove(void) } // do not send 0ms packets because they mess up physics - if(cl.cmd.msec == 0 && cl.time > cl.oldtime && (cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS)) + if(cl.cmd.msec == 0 && cl.time > cl.oldtime && (cls.protocol == &protocol_quakeworld || cls.signon == SIGNONS)) return; // always send if buttons changed or an impulse is pending // even if it violates the rate limit! @@ -1928,12 +1927,12 @@ void CL_SendMove(void) // set prydon cursor info CL_UpdatePrydonCursor(); - if (cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon == SIGNONS) + if (cls.protocol == &protocol_quakeworld || cls.signon == SIGNONS) { - switch (cls.protocol) + switch (cls.protocol->num) { case PROTOCOL_QUAKEWORLD: - MSG_WriteByte(&buf, qw_clc_move); + MSG_WriteByte(&buf, clc_move); // save the position for a checksum byte checksumindex = buf.cursize; MSG_WriteByte(&buf, 0); @@ -1956,14 +1955,13 @@ void CL_SendMove(void) if (cl.qw_validsequence && !cl_nodelta.integer && cls.state == ca_connected && !cls.demorecording) { cl.qw_deltasequence[cls.netcon->outgoing_unreliable_sequence & QW_UPDATE_MASK] = cl.qw_validsequence; - MSG_WriteByte(&buf, qw_clc_delta); + MSG_WriteByte(&buf, clc_delta); MSG_WriteByte(&buf, cl.qw_validsequence & 255); } else cl.qw_deltasequence[cls.netcon->outgoing_unreliable_sequence & QW_UPDATE_MASK] = -1; break; case PROTOCOL_QUAKE: - case PROTOCOL_QUAKEDP: case PROTOCOL_NEHAHRAMOVIE: case PROTOCOL_NEHAHRABJP: case PROTOCOL_NEHAHRABJP2: @@ -2042,7 +2040,7 @@ void CL_SendMove(void) continue; // 5/9 bytes MSG_WriteByte (&buf, clc_move); - if (cls.protocol != PROTOCOL_DARKPLACES6) + if (cls.protocol != &protocol_dpp6) MSG_WriteLong (&buf, cmd->predicted ? cmd->sequence : 0); MSG_WriteFloat (&buf, cmd->time); // last server packet time // 6 bytes @@ -2073,7 +2071,7 @@ void CL_SendMove(void) } } - if (cls.protocol != PROTOCOL_QUAKEWORLD && buf.cursize) + if (cls.protocol != &protocol_quakeworld && buf.cursize) { // ack entity frame numbers received since the last input was sent // (redundent to improve handling of client->server packet loss) diff --git a/cl_main.c b/cl_main.c index de1d5319..ae4c7f99 100644 --- a/cl_main.c +++ b/cl_main.c @@ -248,9 +248,9 @@ void CL_SetInfo(const char *key, const char *value, qbool send, qbool allowstark InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), key, value); if (cls.state == ca_connected && cls.netcon) { - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "setinfo \"%s\" \"%s\"", key, value)); } else if (!strcasecmp(key, "name")) @@ -394,10 +394,10 @@ void CL_Disconnect(void) memset(&buf, 0, sizeof(buf)); buf.data = bufdata; buf.maxsize = sizeof(bufdata); - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { Con_DPrint("Sending drop command\n"); - MSG_WriteByte(&buf, qw_clc_stringcmd); + MSG_WriteByte(&buf, clc_stringcmd); MSG_WriteString(&buf, "drop"); } else @@ -446,7 +446,7 @@ void CL_Reconnect_f(cmd_state_t *cmd) return; } // if connected, do something based on protocol - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { // quakeworld can just re-login if (cls.qw_downloadmemory) // don't change when downloading @@ -457,7 +457,7 @@ void CL_Reconnect_f(cmd_state_t *cmd) if (cls.state == ca_connected) { Con_Printf("Server is changing level...\n"); - MSG_WriteChar(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteChar(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, "new"); } } @@ -1268,7 +1268,7 @@ static void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qbool interp if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) && (e->render.alpha >= 1) && !(e->render.flags & RENDER_VIEWMODEL) - && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) + && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != &protocol_nehahramovie && !cl_noplayershadow.integer))) e->render.flags |= RENDER_SHADOW; if (e->render.flags & RENDER_VIEWMODEL) e->render.flags |= RENDER_NOSELFSHADOW; diff --git a/cl_parse.c b/cl_parse.c index 70467a99..c797d0f1 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // cl_parse.c -- parse a message received from the server #include "quakedef.h" +#include "cl_parse.h" #include "cdaudio.h" #include "cl_collision.h" #include "csprogs.h" @@ -30,138 +31,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include "cl_video.h" -const char *svc_strings[128] = -{ - "svc_bad", - "svc_nop", - "svc_disconnect", - "svc_updatestat", - "svc_version", // [int] 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_serverinfo", // [int] version - // [string] signon string - // [string]..[0]model cache [string]...[0]sounds cache - // [string]..[0]item cache - "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", // [string] music [string] text - "svc_cdtrack", // [byte] track [byte] looptrack - "svc_sellscreen", - "svc_cutscene", - "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y - "svc_hidelmp", // [string] iconlabel - "svc_skybox", // [string] skyname - "", // 38 - "", // 39 - "", // 40 - "", // 41 - "", // 42 - "", // 43 - "", // 44 - "", // 45 - "", // 46 - "", // 47 - "", // 48 - "", // 49 - "svc_downloaddata", // 50 // [int] start [short] size [variable length] data - "svc_updatestatubyte", // 51 // [byte] stat [byte] value - "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate - "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate - "svc_sound2", // 54 // short soundindex instead of byte - "svc_spawnbaseline2", // 55 // short modelindex instead of byte - "svc_spawnstatic2", // 56 // short modelindex instead of byte - "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata - "svc_csqcentities", // 58 // [short] entnum [variable length] entitydata ... [short] 0x0000 - "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten - "svc_trailparticles", // 60 // [short] entnum [short] effectnum [vector] start [vector] end - "svc_pointparticles", // 61 // [short] effectnum [vector] start [vector] velocity [short] count - "svc_pointparticles1", // 62 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 -}; - -const char *qw_svc_strings[128] = -{ - "qw_svc_bad", // 0 - "qw_svc_nop", // 1 - "qw_svc_disconnect", // 2 - "qw_svc_updatestat", // 3 // [byte] [byte] - "", // 4 - "qw_svc_setview", // 5 // [short] entity number - "qw_svc_sound", // 6 // - "", // 7 - "qw_svc_print", // 8 // [byte] id [string] null terminated string - "qw_svc_stufftext", // 9 // [string] stuffed into client's console buffer - "qw_svc_setangle", // 10 // [angle3] set the view angle to this absolute value - "qw_svc_serverdata", // 11 // [long] protocol ... - "qw_svc_lightstyle", // 12 // [byte] [string] - "", // 13 - "qw_svc_updatefrags", // 14 // [byte] [short] - "", // 15 - "qw_svc_stopsound", // 16 // - "", // 17 - "", // 18 - "qw_svc_damage", // 19 - "qw_svc_spawnstatic", // 20 - "", // 21 - "qw_svc_spawnbaseline", // 22 - "qw_svc_temp_entity", // 23 // variable - "qw_svc_setpause", // 24 // [byte] on / off - "", // 25 - "qw_svc_centerprint", // 26 // [string] to put in center of the screen - "qw_svc_killedmonster", // 27 - "qw_svc_foundsecret", // 28 - "qw_svc_spawnstaticsound", // 29 // [coord3] [byte] samp [byte] vol [byte] aten - "qw_svc_intermission", // 30 // [vec3_t] origin [vec3_t] angle - "qw_svc_finale", // 31 // [string] text - "qw_svc_cdtrack", // 32 // [byte] track - "qw_svc_sellscreen", // 33 - "qw_svc_smallkick", // 34 // set client punchangle to 2 - "qw_svc_bigkick", // 35 // set client punchangle to 4 - "qw_svc_updateping", // 36 // [byte] [short] - "qw_svc_updateentertime", // 37 // [byte] [float] - "qw_svc_updatestatlong", // 38 // [byte] [long] - "qw_svc_muzzleflash", // 39 // [short] entity - "qw_svc_updateuserinfo", // 40 // [byte] slot [long] uid - "qw_svc_download", // 41 // [short] size [size bytes] - "qw_svc_playerinfo", // 42 // variable - "qw_svc_nails", // 43 // [byte] num [48 bits] xyzpy 12 12 12 4 8 - "qw_svc_chokecount", // 44 // [byte] packets choked - "qw_svc_modellist", // 45 // [strings] - "qw_svc_soundlist", // 46 // [strings] - "qw_svc_packetentities", // 47 // [...] - "qw_svc_deltapacketentities", // 48 // [...] - "qw_svc_maxspeed", // 49 // maxspeed change, for prediction - "qw_svc_entgravity", // 50 // gravity change, for prediction - "qw_svc_setinfo", // 51 // setinfo on a client - "qw_svc_serverinfo", // 52 // serverinfo - "qw_svc_updatepl", // 53 // [byte] [byte] -}; - //============================================================================= cvar_t cl_worldmessage = {CF_CLIENT | CF_READONLY, "cl_worldmessage", "", "title of current level"}; @@ -201,7 +70,7 @@ static void QW_CL_StopUpload_f(cmd_state_t *cmd); CL_ParseStartSoundPacket ================== */ -static void CL_ParseStartSoundPacket(int largesoundindex) +void CL_ParseStartSoundPacket(int largesoundindex) { vec3_t pos; int channel, ent; @@ -212,7 +81,7 @@ static void CL_ParseStartSoundPacket(int largesoundindex) float speed; int fflags = CHANNELFLAG_NONE; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { channel = MSG_ReadShort(&cl_message); @@ -264,13 +133,13 @@ static void CL_ParseStartSoundPacket(int largesoundindex) channel &= 7; } - if (largesoundindex || (field_mask & SND_LARGESOUND) || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3) + if (largesoundindex || (field_mask & SND_LARGESOUND) || cls.protocol == &protocol_nehahrabjp2 || cls.protocol == &protocol_nehahrabjp3) sound_num = (unsigned short) MSG_ReadShort(&cl_message); else sound_num = MSG_ReadByte(&cl_message); } - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); if (sound_num < 0 || sound_num >= MAX_SOUNDS) { @@ -338,7 +207,7 @@ void CL_KeepaliveMessage (qbool readmessages) } // no need if server is local and definitely not if this is a demo - if (sv.active || !cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon >= SIGNONS) + if (sv.active || !cls.netcon || cls.protocol == &protocol_quakeworld || cls.signon >= SIGNONS) { recursive = thisrecursive; return; @@ -564,7 +433,7 @@ static qbool QW_CL_CheckOrDownloadFile(const char *filename) cls.qw_downloadmemorymaxsize = 1024*1024; // start out with a 1MB buffer } - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "download %s", filename)); cls.qw_downloadnumber++; @@ -616,7 +485,7 @@ static void QW_CL_RequestNextDownload(void) { cls.signon = SIGNONS-1; // we'll go to SIGNONS when the first entity update is received - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "begin %i", cl.qw_servercount)); } break; @@ -686,7 +555,7 @@ static void QW_CL_RequestNextDownload(void) CL_SetInfo("emodel", va(vabuf, sizeof(vabuf), "%i", FS_CRCFile("progs/eyes.mdl", NULL)), true, true, true, true); // done checking sounds and models, send a prespawn command now - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "prespawn %i 0 %i", cl.qw_servercount, cl.model_precache[1]->brush.qw_md4sum2)); if (cls.qw_downloadmemory) @@ -737,7 +606,7 @@ static void QW_CL_RequestNextDownload(void) Mem_CheckSentinelsGlobal(); // done with sound downloads, next we check models - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "modellist %i %i", cl.qw_servercount, 0)); break; case dl_none: @@ -746,7 +615,7 @@ static void QW_CL_RequestNextDownload(void) } } -static void QW_CL_ParseDownload(void) +void QW_CL_ParseDownload(void) { int size = (signed short)MSG_ReadShort(&cl_message); int percent = MSG_ReadByte(&cl_message); @@ -796,7 +665,7 @@ static void QW_CL_ParseDownload(void) if (percent != 100) { // request next fragment - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, "nextdl"); } else @@ -813,7 +682,7 @@ static void QW_CL_ParseDownload(void) } } -static void QW_CL_ParseModelList(void) +void QW_CL_ParseModelList(void) { int n; int nummodels = MSG_ReadByte(&cl_message); @@ -837,7 +706,7 @@ static void QW_CL_ParseModelList(void) n = MSG_ReadByte(&cl_message); if (n) { - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "modellist %i %i", cl.qw_servercount, n)); return; } @@ -848,7 +717,7 @@ static void QW_CL_ParseModelList(void) QW_CL_RequestNextDownload(); } -static void QW_CL_ParseSoundList(void) +void QW_CL_ParseSoundList(void) { int n; int numsounds = MSG_ReadByte(&cl_message); @@ -873,7 +742,7 @@ static void QW_CL_ParseSoundList(void) if (n) { - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "soundlist %i %i", cl.qw_servercount, n)); return; } @@ -915,7 +784,7 @@ void QW_CL_NextUpload_f(cmd_state_t *cmd) size = min(1, cls.qw_uploadsize); percent = (cls.qw_uploadpos+r)*100/size; - MSG_WriteByte(&cls.netcon->message, qw_clc_upload); + MSG_WriteByte(&cls.netcon->message, clc_upload); MSG_WriteShort(&cls.netcon->message, r); MSG_WriteByte(&cls.netcon->message, percent); SZ_Write(&cls.netcon->message, cls.qw_uploaddata + cls.qw_uploadpos, r); @@ -984,7 +853,7 @@ static void QW_CL_ProcessUserInfo(int slot) // TODO: skin cache } -static void QW_CL_UpdateUserInfo(void) +void QW_CL_UpdateUserInfo(void) { int slot; slot = MSG_ReadByte(&cl_message); @@ -1001,7 +870,7 @@ static void QW_CL_UpdateUserInfo(void) QW_CL_ProcessUserInfo(slot); } -static void QW_CL_SetInfo(void) +void QW_CL_SetInfo(void) { int slot; char key[2048]; @@ -1019,7 +888,7 @@ static void QW_CL_SetInfo(void) QW_CL_ProcessUserInfo(slot); } -static void QW_CL_ServerInfo(void) +void QW_CL_ServerInfo(void) { char key[2048]; char value[2048]; @@ -1032,7 +901,7 @@ static void QW_CL_ServerInfo(void) cl.qw_teamplay = atoi(temp); } -static void QW_CL_ParseNails(void) +void QW_CL_ParseNails(void) { int i, j; int numnails = MSG_ReadByte(&cl_message); @@ -1054,7 +923,7 @@ static void QW_CL_ParseNails(void) } } -static void CL_UpdateItemsAndWeapon(void) +void CL_UpdateItemsAndWeapon(void) { int j; // check for important changes @@ -1081,7 +950,7 @@ static void CL_BeginDownloads(qbool aborteddownload) { char vabuf[1024]; // quakeworld works differently - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) return; // this would be a good place to do curl downloads @@ -1467,7 +1336,7 @@ static void CL_StopDownload(int size, int crc) cls.qw_downloadpercent = 0; } -static void CL_ParseDownload(void) +void CL_ParseDownload(void) { int i, start, size; static unsigned char data[NET_MAXMESSAGE]; @@ -1602,7 +1471,7 @@ CL_SignonReply An svc_signonnum has been received, perform a client side setup ===================== */ -static void CL_SignonReply (void) +void CL_SignonReply (void) { Con_DPrintf("CL_SignonReply: %i\n", cls.signon); @@ -1668,11 +1537,11 @@ static void CL_SignonReply (void) CL_ParseServerInfo ================== */ -static void CL_ParseServerInfo (void) +void CL_ParseServerInfo (void) { char *str; int i; - protocolversion_t protocol; + protocol_t *protocol; int nummodels, numsounds; char vabuf[1024]; @@ -1704,21 +1573,21 @@ static void CL_ParseServerInfo (void) // parse protocol version number i = MSG_ReadLong(&cl_message); - protocol = Protocol_EnumForNumber(i); - if (protocol == PROTOCOL_UNKNOWN) + protocol = Protocol_ForNumber(i); + if (!protocol) { Host_Error("CL_ParseServerInfo: Server is unrecognized protocol number (%i)", i); return; } // hack for unmarked Nehahra movie demos which had a custom protocol - if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && gamemode == GAME_NEHAHRA) - protocol = PROTOCOL_NEHAHRAMOVIE; + if (protocol == &protocol_quakedp && cls.demoplayback && gamemode == GAME_NEHAHRA) + protocol = &protocol_nehahramovie; cls.protocol = protocol; - Con_Printf("Server protocol is %s\n", Protocol_NameForEnum(cls.protocol)); + Con_Printf("Server protocol is %s\n", protocol->name); cl.num_entities = 1; - if (protocol == PROTOCOL_QUAKEWORLD) + if (protocol == &protocol_quakeworld) { char gamedir[1][MAX_QPATH]; @@ -1776,7 +1645,7 @@ static void CL_ParseServerInfo (void) if (cls.netcon) { - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "soundlist %i %i", cl.qw_servercount, 0)); } @@ -1816,7 +1685,7 @@ static void CL_ParseServerInfo (void) cl.gametype = MSG_ReadByte(&cl_message); // the original id singleplayer demos are bugged and contain // GAME_DEATHMATCH even for singleplayer - if (cl.maxclients == 1 && cls.protocol == PROTOCOL_QUAKE) + if (cl.maxclients == 1 && cls.protocol == &protocol_netquake) cl.gametype = GAME_COOP; // parse signon message @@ -1824,7 +1693,7 @@ static void CL_ParseServerInfo (void) strlcpy (cl.worldmessage, str, sizeof(cl.worldmessage)); // seperate the printfs so the server message can have a color - if (cls.protocol != PROTOCOL_NEHAHRAMOVIE) // no messages when playing the Nehahra movie + if (cls.protocol != &protocol_nehahramovie) // no messages when playing the Nehahra movie Con_Printf("\n<===================================>\n\n\2%s\n", str); // check memory integrity @@ -1912,7 +1781,7 @@ static void CL_ParseServerInfo (void) Mem_CheckSentinelsGlobal(); // if cl_autodemo is set, automatically start recording a demo if one isn't being recorded already - if (cl_autodemo.integer && cls.netcon && cls.protocol != PROTOCOL_QUAKEWORLD) + if (cl_autodemo.integer && cls.netcon && cls.protocol != &protocol_quakeworld) { char demofile[MAX_OSPATH]; @@ -2093,7 +1962,7 @@ void CL_MoveLerpEntityStates(entity_t *ent) CL_ParseBaseline ================== */ -static void CL_ParseBaseline (entity_t *ent, int large) +void CL_ParseBaseline (entity_t *ent, int large) { int i; @@ -2105,7 +1974,7 @@ static void CL_ParseBaseline (entity_t *ent, int large) ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort(&cl_message); ent->state_baseline.frame = (unsigned short) MSG_ReadShort(&cl_message); } - else if (cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3) + else if (cls.protocol == &protocol_nehahrabjp || cls.protocol == &protocol_nehahrabjp2 || cls.protocol == &protocol_nehahrabjp3) { ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort(&cl_message); ent->state_baseline.frame = MSG_ReadByte(&cl_message); @@ -2119,8 +1988,8 @@ static void CL_ParseBaseline (entity_t *ent, int large) ent->state_baseline.skin = MSG_ReadByte(&cl_message); for (i = 0;i < 3;i++) { - ent->state_baseline.origin[i] = MSG_ReadCoord(&cl_message, cls.protocol); - ent->state_baseline.angles[i] = MSG_ReadAngle(&cl_message, cls.protocol); + ent->state_baseline.origin[i] = cls.protocol->ReadCoord(&cl_message); + ent->state_baseline.angles[i] = cls.protocol->ReadAngle(&cl_message); } ent->state_previous = ent->state_current = ent->state_baseline; } @@ -2133,7 +2002,7 @@ CL_ParseClientdata Server information pertaining to this client only ================== */ -static void CL_ParseClientdata (void) +void CL_ParseClientdata (void) { int i, bits; @@ -2142,7 +2011,7 @@ static void CL_ParseClientdata (void) VectorCopy (cl.mvelocity[0], cl.mvelocity[1]); cl.mviewzoom[1] = cl.mviewzoom[0]; - if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5) + if (cls.protocol == &protocol_netquake || cls.protocol == &protocol_quakedp || cls.protocol == &protocol_nehahramovie || cls.protocol == &protocol_nehahrabjp || cls.protocol == &protocol_nehahrabjp2 || cls.protocol == &protocol_nehahrabjp3 || cls.protocol == &protocol_dpp1 || cls.protocol == &protocol_dpp2 || cls.protocol == &protocol_dpp3 || cls.protocol == &protocol_dpp4 || cls.protocol == &protocol_dpp5) { cl.stats[STAT_VIEWHEIGHT] = DEFAULT_VIEWHEIGHT; cl.stats[STAT_ITEMS] = 0; @@ -2176,21 +2045,21 @@ static void CL_ParseClientdata (void) { if (bits & (SU_PUNCH1<ReadVector(&cl_message, org); + if (large || cls.protocol == &protocol_nehahrabjp2) sound_num = (unsigned short) MSG_ReadShort(&cl_message); else sound_num = MSG_ReadByte(&cl_message); @@ -2317,12 +2186,12 @@ static void CL_ParseStaticSound (int large) S_StaticSound (cl.sound_precache[sound_num], org, vol/255.0f, atten); } -static void CL_ParseEffect (void) +void CL_ParseEffect (void) { vec3_t org; int modelindex, startframe, framecount, framerate; - MSG_ReadVector(&cl_message, org, cls.protocol); + cls.protocol->ReadVector(&cl_message, org); modelindex = MSG_ReadByte(&cl_message); startframe = MSG_ReadByte(&cl_message); framecount = MSG_ReadByte(&cl_message); @@ -2331,12 +2200,12 @@ static void CL_ParseEffect (void) CL_Effect(org, CL_GetModelByIndex(modelindex), startframe, framecount, framerate); } -static void CL_ParseEffect2 (void) +void CL_ParseEffect2 (void) { vec3_t org; int modelindex, startframe, framecount, framerate; - MSG_ReadVector(&cl_message, org, cls.protocol); + cls.protocol->ReadVector(&cl_message, org); modelindex = (unsigned short) MSG_ReadShort(&cl_message); startframe = (unsigned short) MSG_ReadShort(&cl_message); framecount = MSG_ReadByte(&cl_message); @@ -2390,8 +2259,8 @@ static void CL_ParseBeam (dp_model_t *m, int lightning) vec3_t start, end; ent = (unsigned short) MSG_ReadShort(&cl_message); - MSG_ReadVector(&cl_message, start, cls.protocol); - MSG_ReadVector(&cl_message, end, cls.protocol); + cls.protocol->ReadVector(&cl_message, start); + cls.protocol->ReadVector(&cl_message, end); if (ent >= MAX_EDICTS) { @@ -2402,7 +2271,7 @@ static void CL_ParseBeam (dp_model_t *m, int lightning) CL_NewBeam(ent, start, end, m, lightning); } -static void CL_ParseTempEntity(void) +void CL_ParseTempEntity(void) { int type; vec3_t pos, pos2; @@ -2415,14 +2284,14 @@ static void CL_ParseTempEntity(void) unsigned char *tempcolor; matrix4x4_t tempmatrix; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { type = MSG_ReadByte(&cl_message); switch (type) { case QW_TE_WIZSPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_wizhit, pos, 1, 1); @@ -2430,7 +2299,7 @@ static void CL_ParseTempEntity(void) case QW_TE_KNIGHTSPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_knighthit, pos, 1, 1); @@ -2438,7 +2307,7 @@ static void CL_ParseTempEntity(void) case QW_TE_SPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2456,7 +2325,7 @@ static void CL_ParseTempEntity(void) break; case QW_TE_SUPERSPIKE: // super spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2475,7 +2344,7 @@ static void CL_ParseTempEntity(void) case QW_TE_EXPLOSION: // rocket explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); @@ -2484,7 +2353,7 @@ static void CL_ParseTempEntity(void) case QW_TE_TAREXPLOSION: // tarbaby explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); @@ -2506,19 +2375,19 @@ static void CL_ParseTempEntity(void) break; case QW_TE_LAVASPLASH: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case QW_TE_TELEPORT: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case QW_TE_GUNSHOT: // bullet hitting wall radius = MSG_ReadByte(&cl_message); - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); VectorSet(pos2, pos[0] + radius, pos[1] + radius, pos[2] + radius); VectorSet(pos, pos[0] - radius, pos[1] - radius, pos[2] - radius); @@ -2542,13 +2411,13 @@ static void CL_ParseTempEntity(void) case QW_TE_BLOOD: count = MSG_ReadByte(&cl_message); - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_BLOOD, count, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case QW_TE_LIGHTNINGBLOOD: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_BLOOD, 2.5, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; @@ -2564,7 +2433,7 @@ static void CL_ParseTempEntity(void) { case TE_WIZSPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_WIZSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_wizhit, pos, 1, 1); @@ -2572,7 +2441,7 @@ static void CL_ParseTempEntity(void) case TE_KNIGHTSPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_KNIGHTSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_knighthit, pos, 1, 1); @@ -2580,7 +2449,7 @@ static void CL_ParseTempEntity(void) case TE_SPIKE: // spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2598,7 +2467,7 @@ static void CL_ParseTempEntity(void) break; case TE_SPIKEQUAD: // quad spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SPIKEQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2616,7 +2485,7 @@ static void CL_ParseTempEntity(void) break; case TE_SUPERSPIKE: // super spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SUPERSPIKE, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2634,7 +2503,7 @@ static void CL_ParseTempEntity(void) break; case TE_SUPERSPIKEQUAD: // quad super spike hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_SUPERSPIKEQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if (rand() % 5) @@ -2653,7 +2522,7 @@ static void CL_ParseTempEntity(void) // LadyHavoc: added for improved blood splatters case TE_BLOOD: // blood puff - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); dir[0] = MSG_ReadChar(&cl_message); dir[1] = MSG_ReadChar(&cl_message); @@ -2663,7 +2532,7 @@ static void CL_ParseTempEntity(void) break; case TE_SPARK: // spark shower - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); dir[0] = MSG_ReadChar(&cl_message); dir[1] = MSG_ReadChar(&cl_message); @@ -2672,16 +2541,16 @@ static void CL_ParseTempEntity(void) CL_ParticleEffect(EFFECT_TE_SPARK, count, pos, pos, dir, dir, NULL, 0); break; case TE_PLASMABURN: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_PLASMABURN, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; // LadyHavoc: added for improved gore case TE_BLOODSHOWER: // vaporized body - MSG_ReadVector(&cl_message, pos, cls.protocol); // mins - MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs - velspeed = MSG_ReadCoord(&cl_message, cls.protocol); // speed + cls.protocol->ReadVector(&cl_message, pos); // mins + cls.protocol->ReadVector(&cl_message, pos2); // maxs + velspeed = cls.protocol->ReadCoord(&cl_message); // speed count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles vel1[0] = -velspeed; vel1[1] = -velspeed; @@ -2694,21 +2563,21 @@ static void CL_ParseTempEntity(void) case TE_PARTICLECUBE: // general purpose particle effect - MSG_ReadVector(&cl_message, pos, cls.protocol); // mins - MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs - MSG_ReadVector(&cl_message, dir, cls.protocol); // dir + cls.protocol->ReadVector(&cl_message, pos); // mins + cls.protocol->ReadVector(&cl_message, pos2); // maxs + cls.protocol->ReadVector(&cl_message, dir); // dir count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles colorStart = MSG_ReadByte(&cl_message); // color colorLength = MSG_ReadByte(&cl_message); // gravity (1 or 0) - velspeed = MSG_ReadCoord(&cl_message, cls.protocol); // randomvel + velspeed = cls.protocol->ReadCoord(&cl_message); // randomvel CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength != 0, velspeed); break; case TE_PARTICLERAIN: // general purpose particle effect - MSG_ReadVector(&cl_message, pos, cls.protocol); // mins - MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs - MSG_ReadVector(&cl_message, dir, cls.protocol); // dir + cls.protocol->ReadVector(&cl_message, pos); // mins + cls.protocol->ReadVector(&cl_message, pos2); // maxs + cls.protocol->ReadVector(&cl_message, dir); // dir count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles colorStart = MSG_ReadByte(&cl_message); // color CL_ParticleRain(pos, pos2, dir, count, colorStart, 0); @@ -2716,9 +2585,9 @@ static void CL_ParseTempEntity(void) case TE_PARTICLESNOW: // general purpose particle effect - MSG_ReadVector(&cl_message, pos, cls.protocol); // mins - MSG_ReadVector(&cl_message, pos2, cls.protocol); // maxs - MSG_ReadVector(&cl_message, dir, cls.protocol); // dir + cls.protocol->ReadVector(&cl_message, pos); // mins + cls.protocol->ReadVector(&cl_message, pos2); // maxs + cls.protocol->ReadVector(&cl_message, dir); // dir count = (unsigned short) MSG_ReadShort(&cl_message); // number of particles colorStart = MSG_ReadByte(&cl_message); // color CL_ParticleRain(pos, pos2, dir, count, colorStart, 1); @@ -2726,7 +2595,7 @@ static void CL_ParseTempEntity(void) case TE_GUNSHOT: // bullet hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_GUNSHOT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if(cl_sound_ric_gunshot.integer & RIC_GUNSHOT) @@ -2748,7 +2617,7 @@ static void CL_ParseTempEntity(void) case TE_GUNSHOTQUAD: // quad bullet hitting wall - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_GUNSHOTQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); if(cl_sound_ric_gunshot.integer & RIC_GUNSHOTQUAD) @@ -2770,7 +2639,7 @@ static void CL_ParseTempEntity(void) case TE_EXPLOSION: // rocket explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_EXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); @@ -2778,7 +2647,7 @@ static void CL_ParseTempEntity(void) case TE_EXPLOSIONQUAD: // quad rocket explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_EXPLOSIONQUAD, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); @@ -2786,11 +2655,11 @@ static void CL_ParseTempEntity(void) case TE_EXPLOSION3: // Nehahra movie colored lighting explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); - color[0] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f); - color[1] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f); - color[2] = MSG_ReadCoord(&cl_message, cls.protocol) * (2.0f / 1.0f); + color[0] = cls.protocol->ReadCoord(&cl_message) * (2.0f / 1.0f); + color[1] = cls.protocol->ReadCoord(&cl_message) * (2.0f / 1.0f); + color[2] = cls.protocol->ReadCoord(&cl_message) * (2.0f / 1.0f); CL_ParticleExplosion(pos); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocLightFlash(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, NULL, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); @@ -2799,7 +2668,7 @@ static void CL_ParseTempEntity(void) case TE_EXPLOSIONRGB: // colored lighting explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleExplosion(pos); color[0] = MSG_ReadByte(&cl_message) * (2.0f / 255.0f); @@ -2812,20 +2681,20 @@ static void CL_ParseTempEntity(void) case TE_TAREXPLOSION: // tarbaby explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_TAREXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_SMALLFLASH: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_SMALLFLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case TE_CUSTOMFLASH: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 4); radius = (MSG_ReadByte(&cl_message) + 1) * 8; velspeed = (MSG_ReadByte(&cl_message) + 1) * (1.0 / 256.0); @@ -2837,8 +2706,8 @@ static void CL_ParseTempEntity(void) break; case TE_FLAMEJET: - MSG_ReadVector(&cl_message, pos, cls.protocol); - MSG_ReadVector(&cl_message, dir, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); + cls.protocol->ReadVector(&cl_message, dir); count = MSG_ReadByte(&cl_message); CL_ParticleEffect(EFFECT_TE_FLAMEJET, count, pos, pos, dir, dir, NULL, 0); break; @@ -2871,18 +2740,18 @@ static void CL_ParseTempEntity(void) break; case TE_LAVASPLASH: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_ParticleEffect(EFFECT_TE_LAVASPLASH, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case TE_TELEPORT: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_ParticleEffect(EFFECT_TE_TELEPORT, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case TE_EXPLOSION2: // color mapped explosion - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); colorStart = MSG_ReadByte(&cl_message); colorLength = MSG_ReadByte(&cl_message); @@ -2899,30 +2768,30 @@ static void CL_ParseTempEntity(void) break; case TE_TEI_G3: - MSG_ReadVector(&cl_message, pos, cls.protocol); - MSG_ReadVector(&cl_message, pos2, cls.protocol); - MSG_ReadVector(&cl_message, dir, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); + cls.protocol->ReadVector(&cl_message, pos2); + cls.protocol->ReadVector(&cl_message, dir); CL_ParticleTrail(EFFECT_TE_TEI_G3, 1, pos, pos2, dir, dir, NULL, 0, true, true, NULL, NULL, 1); break; case TE_TEI_SMOKE: - MSG_ReadVector(&cl_message, pos, cls.protocol); - MSG_ReadVector(&cl_message, dir, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); + cls.protocol->ReadVector(&cl_message, dir); count = MSG_ReadByte(&cl_message); CL_FindNonSolidLocation(pos, pos, 4); CL_ParticleEffect(EFFECT_TE_TEI_SMOKE, count, pos, pos, vec3_origin, vec3_origin, NULL, 0); break; case TE_TEI_BIGEXPLOSION: - MSG_ReadVector(&cl_message, pos, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); CL_FindNonSolidLocation(pos, pos, 10); CL_ParticleEffect(EFFECT_TE_TEI_BIGEXPLOSION, 1, pos, pos, vec3_origin, vec3_origin, NULL, 0); S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_TEI_PLASMAHIT: - MSG_ReadVector(&cl_message, pos, cls.protocol); - MSG_ReadVector(&cl_message, dir, cls.protocol); + cls.protocol->ReadVector(&cl_message, pos); + cls.protocol->ReadVector(&cl_message, dir); count = MSG_ReadByte(&cl_message); CL_FindNonSolidLocation(pos, pos, 5); CL_ParticleEffect(EFFECT_TE_TEI_PLASMAHIT, count, pos, pos, vec3_origin, vec3_origin, NULL, 0); @@ -2934,7 +2803,7 @@ static void CL_ParseTempEntity(void) } } -static void CL_ParseTrailParticles(void) +void CL_ParseTrailParticles(void) { int entityindex; int effectindex; @@ -2945,28 +2814,28 @@ static void CL_ParseTrailParticles(void) if (entityindex >= cl.max_entities) CL_ExpandEntities(entityindex); effectindex = (unsigned short)MSG_ReadShort(&cl_message); - MSG_ReadVector(&cl_message, start, cls.protocol); - MSG_ReadVector(&cl_message, end, cls.protocol); + cls.protocol->ReadVector(&cl_message, start); + cls.protocol->ReadVector(&cl_message, end); CL_ParticleTrail(effectindex, 1, start, end, vec3_origin, vec3_origin, entityindex > 0 ? cl.entities + entityindex : NULL, 0, true, true, NULL, NULL, 1); } -static void CL_ParsePointParticles(void) +void CL_ParsePointParticles(void) { int effectindex, count; vec3_t origin, velocity; effectindex = (unsigned short)MSG_ReadShort(&cl_message); - MSG_ReadVector(&cl_message, origin, cls.protocol); - MSG_ReadVector(&cl_message, velocity, cls.protocol); + cls.protocol->ReadVector(&cl_message, origin); + cls.protocol->ReadVector(&cl_message, velocity); count = (unsigned short)MSG_ReadShort(&cl_message); CL_ParticleEffect(effectindex, count, origin, origin, velocity, velocity, NULL, 0); } -static void CL_ParsePointParticles1(void) +void CL_ParsePointParticles1(void) { int effectindex; vec3_t origin; effectindex = (unsigned short)MSG_ReadShort(&cl_message); - MSG_ReadVector(&cl_message, origin, cls.protocol); + cls.protocol->ReadVector(&cl_message, origin); CL_ParticleEffect(effectindex, 1, origin, origin, vec3_origin, vec3_origin, NULL, 0); } @@ -3131,7 +3000,7 @@ static void CL_IPLog_List_f(cmd_state_t *cmd) } // look for anything interesting like player IP addresses or ping reports -static qbool CL_ExaminePrintString(const char *text) +qbool CL_ExaminePrintString(const char *text) { int len; const char *t; @@ -3276,7 +3145,7 @@ static qbool CL_ExaminePrintString(const char *text) extern cvar_t host_timescale; extern cvar_t cl_lerpexcess; -static void CL_NetworkTimeReceived(double newtime) +void CL_NetworkTimeReceived(double newtime) { double timehigh; cl.mtime[1] = cl.mtime[0]; @@ -3291,7 +3160,7 @@ static void CL_NetworkTimeReceived(double newtime) if (cl.time < newtime - 0.1) cl.mtime[1] = cl.time = newtime; } - else if (cls.protocol != PROTOCOL_QUAKEWORLD) + else if (cls.protocol != &protocol_quakeworld) { cl.mtime[1] = max(cl.mtime[1], cl.mtime[0] - 0.1); if (developer_extra.integer && vid_activewindow) @@ -3386,13 +3255,10 @@ void CL_ParseServerMessage(void) { int cmd; int i; - protocolversion_t protocol; + protocol_t *protocol = cls.protocol; unsigned char cmdlog[32]; const char *cmdlogname[32], *temp; int cmdindex, cmdcount = 0; - qbool qwplayerupdatereceived; - qbool strip_pqc; - char vabuf[1024]; // LadyHavoc: moved demo message writing from before the packet parse to // after the packet parse so that CL_Stop_f can be called by cl_autodemo @@ -3419,7 +3285,7 @@ void CL_ParseServerMessage(void) parsingerror = true; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (protocol == &protocol_quakeworld) { CL_NetworkTimeReceived(host.realtime); // qw has no clock @@ -3431,369 +3297,29 @@ void CL_ParseServerMessage(void) cls.servermovesequence = cls.netcon->qw.incoming_sequence; - qwplayerupdatereceived = false; - - while (1) - { - if (cl_message.badread) - Host_Error ("CL_ParseServerMessage: Bad QW server message"); - - cmd = MSG_ReadByte(&cl_message); - - if (cmd == -1) - { - SHOWNET("END OF MESSAGE"); - break; // end of message - } - - cmdindex = cmdcount & 31; - cmdcount++; - cmdlog[cmdindex] = cmd; - - SHOWNET(qw_svc_strings[cmd]); - cmdlogname[cmdindex] = qw_svc_strings[cmd]; - if (!cmdlogname[cmdindex]) - { - // LadyHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer) - const char *d = ""; - cmdlogname[cmdindex] = d; - } - - // other commands - switch (cmd) - { - default: - { - char description[32*64], logtemp[64]; - int count; - strlcpy(description, "packet dump: ", sizeof(description)); - i = cmdcount - 32; - if (i < 0) - i = 0; - count = cmdcount - i; - i &= 31; - while(count > 0) - { - dpsnprintf(logtemp, sizeof(logtemp), "%3i:%s ", cmdlog[i], cmdlogname[i]); - strlcat(description, logtemp, sizeof(description)); - count--; - i++; - i &= 31; - } - description[strlen(description)-1] = '\n'; // replace the last space with a newline - Con_Print(description); - Host_Error("CL_ParseServerMessage: Illegible server message"); - } - break; - - case qw_svc_nop: - //Con_Printf("qw_svc_nop\n"); - break; - - case qw_svc_disconnect: - Con_Printf("Server disconnected\n"); - if (cls.demonum != -1) - CL_NextDemo(); - else - CL_Disconnect(); - return; - - case qw_svc_print: - i = MSG_ReadByte(&cl_message); - temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports - { - if (i == 3) // chat - CSQC_AddPrintText(va(vabuf, sizeof(vabuf), "\1%s", temp)); //[515]: csqc - else - CSQC_AddPrintText(temp); - } - break; - - case qw_svc_centerprint: - CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc - break; - - case qw_svc_stufftext: - CL_VM_Parse_StuffCmd(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc - break; - - case qw_svc_damage: - // svc_damage protocol is identical to nq - V_ParseDamage (); - break; - - case qw_svc_serverdata: - //Cbuf_Execute(); // make sure any stuffed commands are done - CL_ParseServerInfo(); - break; - - case qw_svc_setangle: - for (i=0 ; i<3 ; i++) - cl.viewangles[i] = MSG_ReadAngle(&cl_message, cls.protocol); - if (!cls.demoplayback) - { - cl.fixangle[0] = true; - VectorCopy(cl.viewangles, cl.mviewangles[0]); - // disable interpolation if this is new - if (!cl.fixangle[1]) - VectorCopy(cl.viewangles, cl.mviewangles[1]); - } - break; - - case qw_svc_lightstyle: - i = MSG_ReadByte(&cl_message); - if (i >= cl.max_lightstyle) - { - Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); - break; - } - strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map)); - cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; - cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); - break; - - case qw_svc_sound: - CL_ParseStartSoundPacket(false); - break; - - case qw_svc_stopsound: - i = (unsigned short) MSG_ReadShort(&cl_message); - S_StopSound(i>>3, i&7); - break; - - case qw_svc_updatefrags: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients"); - cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message); - break; - - case qw_svc_updateping: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error("CL_ParseServerMessage: svc_updateping >= cl.maxclients"); - cl.scores[i].qw_ping = MSG_ReadShort(&cl_message); - break; - - case qw_svc_updatepl: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error("CL_ParseServerMessage: svc_updatepl >= cl.maxclients"); - cl.scores[i].qw_packetloss = MSG_ReadByte(&cl_message); - break; - - case qw_svc_updateentertime: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error("CL_ParseServerMessage: svc_updateentertime >= cl.maxclients"); - // seconds ago - cl.scores[i].qw_entertime = cl.time - MSG_ReadFloat(&cl_message); - break; - - case qw_svc_spawnbaseline: - i = (unsigned short) MSG_ReadShort(&cl_message); - if (i < 0 || i >= MAX_EDICTS) - Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl.max_entities) - CL_ExpandEntities(i); - CL_ParseBaseline(cl.entities + i, false); - break; - case qw_svc_spawnstatic: - CL_ParseStatic(false); - break; - case qw_svc_temp_entity: - if(!CL_VM_Parse_TempEntity()) - CL_ParseTempEntity (); - break; - - case qw_svc_killedmonster: - cl.stats[STAT_MONSTERS]++; - break; - - case qw_svc_foundsecret: - cl.stats[STAT_SECRETS]++; - break; - - case qw_svc_updatestat: - i = MSG_ReadByte(&cl_message); - if (i < 0 || i >= MAX_CL_STATS) - Host_Error ("svc_updatestat: %i is invalid", i); - cl.stats[i] = MSG_ReadByte(&cl_message); - break; - - case qw_svc_updatestatlong: - i = MSG_ReadByte(&cl_message); - if (i < 0 || i >= MAX_CL_STATS) - Host_Error ("svc_updatestatlong: %i is invalid", i); - cl.stats[i] = MSG_ReadLong(&cl_message); - break; - - case qw_svc_spawnstaticsound: - CL_ParseStaticSound (false); - break; - - case qw_svc_cdtrack: - cl.cdtrack = cl.looptrack = MSG_ReadByte(&cl_message); - if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) - CDAudio_Play ((unsigned char)cls.forcetrack, true); - else - CDAudio_Play ((unsigned char)cl.cdtrack, true); - break; - - case qw_svc_intermission: - if(!cl.intermission) - cl.completed_time = cl.time; - cl.intermission = 1; - MSG_ReadVector(&cl_message, cl.qw_intermission_origin, cls.protocol); - for (i = 0;i < 3;i++) - cl.qw_intermission_angles[i] = MSG_ReadAngle(&cl_message, cls.protocol); - break; - - case qw_svc_finale: - if(!cl.intermission) - cl.completed_time = cl.time; - cl.intermission = 2; - SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); - break; - - case qw_svc_sellscreen: - Cmd_ExecuteString(&cmd_client, "help", src_local, true); - break; - - case qw_svc_smallkick: - cl.qw_weaponkick = -2; - break; - case qw_svc_bigkick: - cl.qw_weaponkick = -4; - break; - - case qw_svc_muzzleflash: - i = (unsigned short) MSG_ReadShort(&cl_message); - // NOTE: in QW this only worked on clients - if (i < 0 || i >= MAX_EDICTS) - Host_Error("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl.max_entities) - CL_ExpandEntities(i); - cl.entities[i].persistent.muzzleflash = 1.0f; - break; - - case qw_svc_updateuserinfo: - QW_CL_UpdateUserInfo(); - break; - - case qw_svc_setinfo: - QW_CL_SetInfo(); - break; - - case qw_svc_serverinfo: - QW_CL_ServerInfo(); - break; - - case qw_svc_download: - QW_CL_ParseDownload(); - break; - - case qw_svc_playerinfo: - // slightly kill qw player entities now that we know there is - // an update of player entities this frame... - if (!qwplayerupdatereceived) - { - qwplayerupdatereceived = true; - for (i = 1;i < cl.maxclients;i++) - cl.entities_active[i] = false; - } - EntityStateQW_ReadPlayerUpdate(); - break; - - case qw_svc_nails: - QW_CL_ParseNails(); - break; - - case qw_svc_chokecount: - (void) MSG_ReadByte(&cl_message); - // FIXME: apply to netgraph - //for (j = 0;j < i;j++) - // cl.frames[(cls.netcon->qw.incoming_acknowledged-1-j)&QW_UPDATE_MASK].receivedtime = -2; - break; - - case qw_svc_modellist: - QW_CL_ParseModelList(); - break; - - case qw_svc_soundlist: - QW_CL_ParseSoundList(); - break; - - case qw_svc_packetentities: - EntityFrameQW_CL_ReadFrame(false); - // first update is the final signon stage - if (cls.signon == SIGNONS - 1) - { - cls.signon = SIGNONS; - CL_SignonReply (); - } - break; - - case qw_svc_deltapacketentities: - EntityFrameQW_CL_ReadFrame(true); - // first update is the final signon stage - if (cls.signon == SIGNONS - 1) - { - cls.signon = SIGNONS; - CL_SignonReply (); - } - break; - - case qw_svc_maxspeed: - cl.movevars_maxspeed = MSG_ReadFloat(&cl_message); - break; - - case qw_svc_entgravity: - cl.movevars_entgravity = MSG_ReadFloat(&cl_message); - if (!cl.movevars_entgravity) - cl.movevars_entgravity = 1.0f; - break; - - case qw_svc_setpause: - cl.paused = MSG_ReadByte(&cl_message) != 0; - if (cl.paused) - CDAudio_Pause (); - else - CDAudio_Resume (); - S_PauseGameSounds (cl.paused); - break; - } - } - - if (qwplayerupdatereceived) - { - // fully kill any player entities that were not updated this frame - for (i = 1;i <= cl.maxclients;i++) - if (!cl.entities_active[i]) - cl.entities[i].state_current.active = false; - } + cl.qwplayerupdatereceived = false; } - else + + while (1) { - while (1) - { - if (cl_message.badread) - Host_Error ("CL_ParseServerMessage: Bad server message"); + if (cl_message.badread) + Host_Error ("CL_ParseServerMessage: Bad server message"); - cmd = MSG_ReadByte(&cl_message); + cmd = MSG_ReadByte(&cl_message); - if (cmd == -1) - { + if (cmd == -1) + { // R_TimeReport("END OF MESSAGE"); - SHOWNET("END OF MESSAGE"); - break; // end of message - } + SHOWNET("END OF MESSAGE"); + break; // end of message + } - cmdindex = cmdcount & 31; - cmdcount++; - cmdlog[cmdindex] = cmd; + cmdindex = cmdcount & 31; + cmdcount++; + cmdlog[cmdindex] = cmd; + if(protocol != &protocol_quakeworld) + { // if the high bit of the command byte is set, it is a fast update if (cmd & 128) { @@ -3810,431 +3336,53 @@ void CL_ParseServerMessage(void) EntityFrameQuake_ReadEntity (cmd&127); continue; } + } - SHOWNET(svc_strings[cmd]); - cmdlogname[cmdindex] = svc_strings[cmd]; + if(cmd <= protocol->max_svcmsg && protocol->svcmsg[cmd].func) + { + SHOWNET(protocol->svcmsg[cmd].name); + cmdlogname[cmdindex] = protocol->svcmsg[cmd].name; if (!cmdlogname[cmdindex]) { // LadyHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer) const char *d = ""; cmdlogname[cmdindex] = d; } - - // other commands - switch (cmd) + protocol->svcmsg[cmd].func(protocol); + } + else + { + char description[32*64], tempdesc[64]; + int count; + strlcpy (description, "packet dump: ", sizeof(description)); + i = cmdcount - 32; + if (i < 0) + i = 0; + count = cmdcount - i; + i &= 31; + while(count > 0) { - default: - { - char description[32*64], tempdesc[64]; - int count; - strlcpy (description, "packet dump: ", sizeof(description)); - i = cmdcount - 32; - if (i < 0) - i = 0; - count = cmdcount - i; - i &= 31; - while(count > 0) - { - dpsnprintf (tempdesc, sizeof (tempdesc), "%3i:%s ", cmdlog[i], cmdlogname[i]); - strlcat (description, tempdesc, sizeof (description)); - count--; - i++; - i &= 31; - } - description[strlen(description)-1] = '\n'; // replace the last space with a newline - Con_Print(description); - Host_Error ("CL_ParseServerMessage: Illegible server message"); - } - break; - - case svc_nop: - if (cls.signon < SIGNONS) - Con_Print("<-- server to client keepalive\n"); - break; - - case svc_time: - CL_NetworkTimeReceived(MSG_ReadFloat(&cl_message)); - break; - - case svc_clientdata: - CL_ParseClientdata(); - break; - - case svc_version: - i = MSG_ReadLong(&cl_message); - protocol = Protocol_EnumForNumber(i); - if (protocol == PROTOCOL_UNKNOWN) - Host_Error("CL_ParseServerMessage: Server is unrecognized protocol number (%i)", i); - // hack for unmarked Nehahra movie demos which had a custom protocol - if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && gamemode == GAME_NEHAHRA) - protocol = PROTOCOL_NEHAHRAMOVIE; - cls.protocol = protocol; - break; - - case svc_disconnect: - Con_Printf ("Server disconnected\n"); - if (cls.demonum != -1) - CL_NextDemo (); - else - CL_Disconnect (); - break; - - case svc_print: - temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports - CSQC_AddPrintText(temp); //[515]: csqc - break; - - case svc_centerprint: - CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc - break; - - case svc_stufftext: - temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - /* if(utf8_enable.integer) - { - strip_pqc = true; - // we can safely strip and even - // interpret these in utf8 mode - } - else */ switch(cls.protocol) - { - case PROTOCOL_QUAKE: - case PROTOCOL_QUAKEDP: - // maybe add other protocols if - // so desired, but not DP7 - strip_pqc = true; - break; - case PROTOCOL_DARKPLACES7: - default: - // ProQuake does not support - // these protocols - strip_pqc = false; - break; - } - if(strip_pqc) - { - // skip over ProQuake messages, - // TODO actually interpret them - // (they are sbar team score - // updates), see proquake cl_parse.c - if(*temp == 0x01) - { - ++temp; - while(*temp >= 0x01 && *temp <= 0x1F) - ++temp; - } - } - CL_VM_Parse_StuffCmd(temp); //[515]: csqc - break; - - case svc_damage: - V_ParseDamage (); - break; - - case svc_serverinfo: - CL_ParseServerInfo (); - break; - - case svc_setangle: - for (i=0 ; i<3 ; i++) - cl.viewangles[i] = MSG_ReadAngle(&cl_message, cls.protocol); - if (!cls.demoplayback) - { - cl.fixangle[0] = true; - VectorCopy(cl.viewangles, cl.mviewangles[0]); - // disable interpolation if this is new - if (!cl.fixangle[1]) - VectorCopy(cl.viewangles, cl.mviewangles[1]); - } - break; - - case svc_setview: - cl.viewentity = (unsigned short)MSG_ReadShort(&cl_message); - if (cl.viewentity >= MAX_EDICTS) - Host_Error("svc_setview >= MAX_EDICTS"); - if (cl.viewentity >= cl.max_entities) - CL_ExpandEntities(cl.viewentity); - // LadyHavoc: assume first setview recieved is the real player entity - if (!cl.realplayerentity) - cl.realplayerentity = cl.viewentity; - // update cl.playerentity to this one if it is a valid player - if (cl.viewentity >= 1 && cl.viewentity <= cl.maxclients) - cl.playerentity = cl.viewentity; - break; - - case svc_lightstyle: - i = MSG_ReadByte(&cl_message); - if (i >= cl.max_lightstyle) - { - Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); - break; - } - strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map)); - cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; - cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); - break; - - case svc_sound: - CL_ParseStartSoundPacket(false); - break; - - case svc_precache: - if (cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3) - { - // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6 - CL_ParseStartSoundPacket(true); - } - else - { - char *s; - i = (unsigned short)MSG_ReadShort(&cl_message); - s = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - if (i < 32768) - { - if (i >= 1 && i < MAX_MODELS) - { - dp_model_t *model = Mod_ForName(s, false, false, s[0] == '*' ? cl.model_name[1] : NULL); - if (!model) - Con_DPrintf("svc_precache: Mod_ForName(\"%s\") failed\n", s); - cl.model_precache[i] = model; - } - else - Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_MODELS); - } - else - { - i -= 32768; - if (i >= 1 && i < MAX_SOUNDS) - { - sfx_t *sfx = S_PrecacheSound (s, true, true); - if (!sfx && snd_initialized.integer) - Con_DPrintf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s); - cl.sound_precache[i] = sfx; - } - else - Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_SOUNDS); - } - } - break; - - case svc_stopsound: - i = (unsigned short) MSG_ReadShort(&cl_message); - S_StopSound(i>>3, i&7); - break; - - case svc_updatename: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients"); - strlcpy (cl.scores[i].name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.scores[i].name)); - break; - - case svc_updatefrags: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients"); - cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message); - break; - - case svc_updatecolors: - i = MSG_ReadByte(&cl_message); - if (i >= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients"); - cl.scores[i].colors = MSG_ReadByte(&cl_message); - break; - - case svc_particle: - CL_ParseParticleEffect (); - break; - - case svc_effect: - CL_ParseEffect (); - break; - - case svc_effect2: - CL_ParseEffect2 (); - break; - - case svc_spawnbaseline: - i = (unsigned short) MSG_ReadShort(&cl_message); - if (i < 0 || i >= MAX_EDICTS) - Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl.max_entities) - CL_ExpandEntities(i); - CL_ParseBaseline (cl.entities + i, false); - break; - case svc_spawnbaseline2: - i = (unsigned short) MSG_ReadShort(&cl_message); - if (i < 0 || i >= MAX_EDICTS) - Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i); - if (i >= cl.max_entities) - CL_ExpandEntities(i); - CL_ParseBaseline (cl.entities + i, true); - break; - case svc_spawnstatic: - CL_ParseStatic (false); - break; - case svc_spawnstatic2: - CL_ParseStatic (true); - break; - case svc_temp_entity: - if(!CL_VM_Parse_TempEntity()) - CL_ParseTempEntity (); - break; - - case svc_setpause: - cl.paused = MSG_ReadByte(&cl_message) != 0; - if (cl.paused) - CDAudio_Pause (); - else - CDAudio_Resume (); - S_PauseGameSounds (cl.paused); - break; - - case svc_signonnum: - i = MSG_ReadByte(&cl_message); - // LadyHavoc: it's rude to kick off the client if they missed the - // reconnect somehow, so allow signon 1 even if at signon 1 - if (i <= cls.signon && i != 1) - Host_Error ("Received signon %i when at %i", i, cls.signon); - cls.signon = i; - CL_SignonReply (); - break; - - case svc_killedmonster: - cl.stats[STAT_MONSTERS]++; - break; - - case svc_foundsecret: - cl.stats[STAT_SECRETS]++; - break; - - case svc_updatestat: - i = MSG_ReadByte(&cl_message); - if (i < 0 || i >= MAX_CL_STATS) - Host_Error ("svc_updatestat: %i is invalid", i); - cl.stats[i] = MSG_ReadLong(&cl_message); - break; - - case svc_updatestatubyte: - i = MSG_ReadByte(&cl_message); - if (i < 0 || i >= MAX_CL_STATS) - Host_Error ("svc_updatestat: %i is invalid", i); - cl.stats[i] = MSG_ReadByte(&cl_message); - break; - - case svc_spawnstaticsound: - CL_ParseStaticSound (false); - break; - - case svc_spawnstaticsound2: - CL_ParseStaticSound (true); - break; - - case svc_cdtrack: - cl.cdtrack = MSG_ReadByte(&cl_message); - cl.looptrack = MSG_ReadByte(&cl_message); - if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) - CDAudio_Play ((unsigned char)cls.forcetrack, true); - else - CDAudio_Play ((unsigned char)cl.cdtrack, true); - break; - - case svc_intermission: - if(!cl.intermission) - cl.completed_time = cl.time; - cl.intermission = 1; - CL_VM_UpdateIntermissionState(cl.intermission); - break; - - case svc_finale: - if(!cl.intermission) - cl.completed_time = cl.time; - cl.intermission = 2; - CL_VM_UpdateIntermissionState(cl.intermission); - SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); - break; - - case svc_cutscene: - if(!cl.intermission) - cl.completed_time = cl.time; - cl.intermission = 3; - CL_VM_UpdateIntermissionState(cl.intermission); - SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); - break; - - case svc_sellscreen: - Cmd_ExecuteString(&cmd_client, "help", src_local, true); - break; - case svc_hidelmp: - if (gamemode == GAME_TENEBRAE) - { - // repeating particle effect - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - (void) MSG_ReadByte(&cl_message); - MSG_ReadLong(&cl_message); - MSG_ReadLong(&cl_message); - MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - } - else - SHOWLMP_decodehide(); - break; - case svc_showlmp: - if (gamemode == GAME_TENEBRAE) - { - // particle effect - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - MSG_ReadCoord(&cl_message, cls.protocol); - (void) MSG_ReadByte(&cl_message); - MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); - } - else - SHOWLMP_decodeshow(); - break; - case svc_skybox: - R_SetSkyBox(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); - break; - case svc_entities: - if (cls.signon == SIGNONS - 1) - { - // first update is the final signon stage - cls.signon = SIGNONS; - CL_SignonReply (); - } - if (cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3) - EntityFrame_CL_ReadFrame(); - else if (cls.protocol == PROTOCOL_DARKPLACES4) - EntityFrame4_CL_ReadFrame(); - else - EntityFrame5_CL_ReadFrame(); - break; - case svc_csqcentities: - CSQC_ReadEntities(); - break; - case svc_downloaddata: - CL_ParseDownload(); - break; - case svc_trailparticles: - CL_ParseTrailParticles(); - break; - case svc_pointparticles: - CL_ParsePointParticles(); - break; - case svc_pointparticles1: - CL_ParsePointParticles1(); - break; + dpsnprintf (tempdesc, sizeof (tempdesc), "%3i:%s ", cmdlog[i], cmdlogname[i]); + strlcat (description, tempdesc, sizeof (description)); + count--; + i++; + i &= 31; } -// R_TimeReport(svc_strings[cmd]); + description[strlen(description)-1] = '\n'; // replace the last space with a newline + Con_Print(description); + Host_Error ("CL_ParseServerMessage: Illegible server message"); } } + if (cl.qwplayerupdatereceived) + { + // fully kill any player entities that were not updated this frame + for (i = 1;i <= cl.maxclients;i++) + if (!cl.entities_active[i]) + cl.entities[i].state_current.active = false; + } +// R_TimeReport(svc_strings[cmd]); + if (cls.signon == SIGNONS) CL_UpdateItemsAndWeapon(); // R_TimeReport("UpdateItems"); diff --git a/cl_parse.h b/cl_parse.h new file mode 100644 index 00000000..8c1437e3 --- /dev/null +++ b/cl_parse.h @@ -0,0 +1,26 @@ +#include "quakedef.h" + +void CL_ParseBaseline (entity_t *ent, int large); +void CL_ParseClientdata (void); +void CL_ParseStatic (int large); +void CL_ParseStaticSound (int large); +void CL_ParseEffect (void); +void CL_ParseEffect2 (void); +void CL_ParseServerInfo (void); +qbool CL_ExaminePrintString(const char *text); +void CL_ParseStartSoundPacket(int largesoundindex); +void CL_ParseTempEntity(void); +void QW_CL_UpdateUserInfo(void); +void QW_CL_SetInfo(void); +void QW_CL_ServerInfo(void); +void QW_CL_ParseDownload(void); +void QW_CL_ParseModelList(void); +void QW_CL_ParseNails(void); +void CL_UpdateItemsAndWeapon(void); +void QW_CL_ParseSoundList(void); +void CL_SignonReply (void); +void CL_NetworkTimeReceived(double newtime); +void CL_ParseDownload(void); +void CL_ParseTrailParticles(void); +void CL_ParsePointParticles(void); +void CL_ParsePointParticles1(void); \ No newline at end of file diff --git a/cl_particles.c b/cl_particles.c index f6da3601..9d463862 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -1769,7 +1769,7 @@ void CL_ParseParticleEffect (void) vec3_t org, dir; int i, count, msgcount, color; - MSG_ReadVector(&cl_message, org, cls.protocol); + cls.protocol->ReadVector(&cl_message, org); for (i=0 ; i<3 ; i++) dir[i] = MSG_ReadChar(&cl_message) * (1.0 / 16.0); msgcount = MSG_ReadByte(&cl_message); diff --git a/cl_protocol_basenq.h b/cl_protocol_basenq.h new file mode 100644 index 00000000..1f5edbaf --- /dev/null +++ b/cl_protocol_basenq.h @@ -0,0 +1,336 @@ +#include "quakedef.h" +#include "client.h" +#include "protocol.h" +#include "cl_parse.h" +#include "cdaudio.h" + +static void Netmsg_svc_nop (protocol_t *protocol) +{ + if (cls.signon < SIGNONS) + Con_Print("<-- server to client keepalive\n"); + +} + +static void Netmsg_svc_disconnect (protocol_t *protocol) +{ + Con_Printf ("Server disconnected\n"); + if (cls.demonum != -1) + CL_NextDemo (); + else + CL_Disconnect (); +} + +static void Netmsg_svc_updatestat (protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i < 0 || i >= MAX_CL_STATS) + Host_Error ("svc_updatestat: %i is invalid", i); + cl.stats[i] = MSG_ReadLong(&cl_message); +} + +static void Netmsg_svc_version (protocol_t *protocol) // [int] server version +{ + int i = MSG_ReadLong(&cl_message); + if (!Protocol_ForNumber(i)) + Host_Error("CL_ParseServerMessage: Server is unrecognized protocol number (%i)", i); + // hack for unmarked Nehahra movie demos which had a custom protocol + if (protocol == &protocol_quakedp && cls.demoplayback && gamemode == GAME_NEHAHRA) + protocol = &protocol_nehahramovie; + cls.protocol = protocol; +} + +static void Netmsg_svc_setview (protocol_t *protocol) // [short] entity number +{ + cl.viewentity = (unsigned short)MSG_ReadShort(&cl_message); + if (cl.viewentity >= MAX_EDICTS) + Host_Error("svc_setview >= MAX_EDICTS"); + if (cl.viewentity >= cl.max_entities) + CL_ExpandEntities(cl.viewentity); + // LadyHavoc: assume first setview recieved is the real player entity + if (!cl.realplayerentity) + cl.realplayerentity = cl.viewentity; + // update cl.playerentity to this one if it is a valid player + if (cl.viewentity >= 1 && cl.viewentity <= cl.maxclients) + cl.playerentity = cl.viewentity; + +} + +static void Netmsg_svc_sound (protocol_t *protocol) // +{ + CL_ParseStartSoundPacket(false); +} + +static void Netmsg_svc_time (protocol_t *protocol) // [float] server time +{ + CL_NetworkTimeReceived(MSG_ReadFloat(&cl_message)); +} + +static void Netmsg_svc_print (protocol_t *protocol) // [string] null terminated string +{ + const char *temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports + CSQC_AddPrintText(temp); //[515]: csqc +} + +static void Netmsg_svc_stufftext (protocol_t *protocol) // [string] stuffed into client's console buffer +{ // the string should be \n terminated + qbool strip_pqc; + const char *temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + /* if(utf8_enable.integer) + { + strip_pqc = true; + // we can safely strip and even + // interpret these in utf8 mode + } + else */ switch(cls.protocol->num) + { + case PROTOCOL_QUAKE: + // maybe add other protocols if + // so desired, but not DP7 + strip_pqc = true; + break; + default: + // ProQuake does not support + // these protocols + strip_pqc = false; + break; + } + if(strip_pqc) + { + // skip over ProQuake messages, + // TODO actually interpret them + // (they are sbar team score + // updates), see proquake cl_parse.c + if(*temp == 0x01) + { + ++temp; + while(*temp >= 0x01 && *temp <= 0x1F) + ++temp; + } + } + CL_VM_Parse_StuffCmd(temp); //[515]: csqc + +} + +static void Netmsg_svc_setangle (protocol_t *protocol) // [vec3] set the view angle to this absolute value +{ + int i; + for (i=0 ; i<3 ; i++) + cl.viewangles[i] = protocol->ReadAngle(&cl_message); + if (!cls.demoplayback) + { + cl.fixangle[0] = true; + VectorCopy(cl.viewangles, cl.mviewangles[0]); + // disable interpolation if this is new + if (!cl.fixangle[1]) + VectorCopy(cl.viewangles, cl.mviewangles[1]); + } +} + +static void Netmsg_svc_serverinfo (protocol_t *protocol) // [int] version + // [string] signon string + // [string]..[0]model cache [string]...[0]sounds cache + // [string]..[0]item cache +{ + CL_ParseServerInfo (); +} + +static void Netmsg_svc_lightstyle (protocol_t *protocol) // [byte] [string] +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.max_lightstyle) + { + Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); + return; + } + strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map)); + cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; + cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); +} + +static void Netmsg_svc_updatename (protocol_t *protocol) // [byte] [string] +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients"); + strlcpy (cl.scores[i].name, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.scores[i].name)); +} + +static void Netmsg_svc_updatefrags (protocol_t *protocol) // [byte] [short] +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients"); + cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message); +} + +static void Netmsg_svc_clientdata (protocol_t *protocol) // +{ + CL_ParseClientdata(); +} + +static void Netmsg_svc_stopsound (protocol_t *protocol) // +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + S_StopSound(i>>3, i&7); +} + +static void Netmsg_svc_updatecolors (protocol_t *protocol) // [byte] [byte] +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients"); + cl.scores[i].colors = MSG_ReadByte(&cl_message); + +} + +static void Netmsg_svc_particle (protocol_t *protocol) // [vec3] +{ + CL_ParseParticleEffect (); +} + +static void Netmsg_svc_damage (protocol_t *protocol) // [byte] impact [byte] blood [vec3] from +{ + V_ParseDamage (); +} + +static void Netmsg_svc_spawnstatic (protocol_t *protocol) +{ + CL_ParseStatic (false); +} + +static void Netmsg_svc_spawnbaseline (protocol_t *protocol) +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + if (i < 0 || i >= MAX_EDICTS) + Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); + if (i >= cl.max_entities) + CL_ExpandEntities(i); + CL_ParseBaseline (cl.entities + i, false); +} + +static void Netmsg_svc_temp_entity (protocol_t *protocol) // +{ + if(!CL_VM_Parse_TempEntity()) + CL_ParseTempEntity (); +} + +static void Netmsg_svc_setpause (protocol_t *protocol) +{ + cl.paused = MSG_ReadByte(&cl_message) != 0; + if (cl.paused) + CDAudio_Pause (); + else + CDAudio_Resume (); + S_PauseGameSounds (cl.paused); +} + +static void Netmsg_svc_signonnum (protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + // LadyHavoc: it's rude to kick off the client if they missed the + // reconnect somehow, so allow signon 1 even if at signon 1 + if (i <= cls.signon && i != 1) + Host_Error ("Received signon %i when at %i", i, cls.signon); + cls.signon = i; + CL_SignonReply (); +} + +static void Netmsg_svc_centerprint (protocol_t *protocol) +{ + CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc +} + +static void Netmsg_svc_killedmonster (protocol_t *protocol) +{ + cl.stats[STAT_MONSTERS]++; +} + +static void Netmsg_svc_foundsecret (protocol_t *protocol) +{ + cl.stats[STAT_SECRETS]++; +} + +static void Netmsg_svc_spawnstaticsound (protocol_t *protocol) +{ + CL_ParseStaticSound (false); +} + +static void Netmsg_svc_intermission (protocol_t *protocol) +{ + if(!cl.intermission) + cl.completed_time = cl.time; + cl.intermission = 1; + CL_VM_UpdateIntermissionState(cl.intermission); +} + +static void Netmsg_svc_finale (protocol_t *protocol) // [string] music [string] text +{ + if(!cl.intermission) + cl.completed_time = cl.time; + cl.intermission = 2; + CL_VM_UpdateIntermissionState(cl.intermission); + SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); +} + +static void Netmsg_svc_cdtrack (protocol_t *protocol) // [byte] track [byte] looptrack +{ + cl.cdtrack = MSG_ReadByte(&cl_message); + cl.looptrack = MSG_ReadByte(&cl_message); + if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) + CDAudio_Play ((unsigned char)cls.forcetrack, true); + else + CDAudio_Play ((unsigned char)cl.cdtrack, true); + +} + +static void Netmsg_svc_sellscreen (protocol_t *protocol) +{ + Cmd_ExecuteString(&cmd_client, "help", src_local, true); +} + +static void Netmsg_svc_cutscene (protocol_t *protocol) +{ + if(!cl.intermission) + cl.completed_time = cl.time; + cl.intermission = 3; + CL_VM_UpdateIntermissionState(cl.intermission); + SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); +} + +#define NETMSG_BASENQ_SVC \ + {"svc_bad", NULL}, \ + {"svc_nop", Netmsg_svc_nop}, \ + {"svc_disconnect", Netmsg_svc_disconnect}, \ + {"svc_updatestat", Netmsg_svc_updatestat}, \ + {"svc_version", Netmsg_svc_version}, \ + {"svc_setview", Netmsg_svc_setview}, \ + {"svc_sound", Netmsg_svc_sound}, \ + {"svc_time", Netmsg_svc_time}, \ + {"svc_print", Netmsg_svc_print}, \ + {"svc_stufftext", Netmsg_svc_stufftext}, \ + {"svc_setangle", Netmsg_svc_setangle}, \ + {"svc_serverinfo", Netmsg_svc_serverinfo}, \ + {"svc_lightstyle", Netmsg_svc_lightstyle}, \ + {"svc_updatename", Netmsg_svc_updatename}, \ + {"svc_updatefrags", Netmsg_svc_updatefrags}, \ + {"svc_clientdata", Netmsg_svc_clientdata}, \ + {"svc_stopsound", Netmsg_svc_stopsound}, \ + {"svc_updatecolors", Netmsg_svc_updatecolors}, \ + {"svc_particle", Netmsg_svc_particle}, \ + {"svc_damage",Netmsg_svc_damage}, \ + {"svc_spawnstatic", Netmsg_svc_spawnstatic}, \ + {"OBSOLETE svc_spawnbinary", NULL}, \ + {"svc_spawnbaseline", Netmsg_svc_spawnbaseline}, \ + {"svc_temp_entity", Netmsg_svc_temp_entity}, \ + {"svc_setpause", Netmsg_svc_setpause}, \ + {"svc_signonnum", Netmsg_svc_signonnum}, \ + {"svc_centerprint", Netmsg_svc_centerprint}, \ + {"svc_killedmonster", Netmsg_svc_killedmonster}, \ + {"svc_foundsecret", Netmsg_svc_foundsecret}, \ + {"svc_spawnstaticsound", Netmsg_svc_spawnstaticsound}, \ + {"svc_intermission", Netmsg_svc_intermission}, \ + {"svc_finale", Netmsg_svc_finale}, \ + {"svc_cdtrack", Netmsg_svc_cdtrack}, \ + {"svc_sellscreen", Netmsg_svc_sellscreen}, \ + {"svc_cutscene", Netmsg_svc_cutscene} diff --git a/cl_protocol_baseqw.h b/cl_protocol_baseqw.h new file mode 100644 index 00000000..f8346157 --- /dev/null +++ b/cl_protocol_baseqw.h @@ -0,0 +1,336 @@ +#include "quakedef.h" +#include "client.h" +#include "protocol.h" +#include "cl_parse.h" +#include "cdaudio.h" + +static void Netmsg_svc_nop(protocol_t *protocol) +{ + //Con_Printf("qw_svc_nop\n"); +} + +static void Netmsg_svc_disconnect(protocol_t *protocol) +{ + Con_Printf("Server disconnected\n"); + if (cls.demonum != -1) + CL_NextDemo(); + else + CL_Disconnect(); + return; +} + +static void Netmsg_svc_print(protocol_t *protocol) +{ + char vabuf[1024]; + int i = MSG_ReadByte(&cl_message); + char *temp = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + if (CL_ExaminePrintString(temp)) // look for anything interesting like player IP addresses or ping reports + { + if (i == 3) // chat + CSQC_AddPrintText(va(vabuf, sizeof(vabuf), "\1%s", temp)); //[515]: csqc + else + CSQC_AddPrintText(temp); + } +} + +static void Netmsg_svc_centerprint(protocol_t *protocol) +{ + CL_VM_Parse_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc +} + +static void Netmsg_svc_stufftext(protocol_t *protocol) +{ + CL_VM_Parse_StuffCmd(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); //[515]: csqc +} + +static void Netmsg_svc_damage(protocol_t *protocol) +{ + // svc_damage protocol is identical to nq + V_ParseDamage (); +} + +static void Netmsg_svc_serverdata(protocol_t *protocol) +{ + //Cbuf_Execute(); // make sure any stuffed commands are done + CL_ParseServerInfo(); +} + +static void Netmsg_svc_setangle(protocol_t *protocol) +{ + int i; + for (i=0 ; i<3 ; i++) + cl.viewangles[i] = protocol->ReadAngle(&cl_message); + if (!cls.demoplayback) + { + cl.fixangle[0] = true; + VectorCopy(cl.viewangles, cl.mviewangles[0]); + // disable interpolation if this is new + if (!cl.fixangle[1]) + VectorCopy(cl.viewangles, cl.mviewangles[1]); + } +} + +static void Netmsg_svc_lightstyle(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.max_lightstyle) + { + Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); + return; + } + strlcpy (cl.lightstyle[i].map, MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)), sizeof (cl.lightstyle[i].map)); + cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; + cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); +} + +static void Netmsg_svc_sound(protocol_t *protocol) +{ + CL_ParseStartSoundPacket(false); +} + +static void Netmsg_svc_stopsound(protocol_t *protocol) +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + S_StopSound(i>>3, i&7); +} + +static void Netmsg_svc_updatefrags(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients"); + cl.scores[i].frags = (signed short) MSG_ReadShort(&cl_message); +} + +static void Netmsg_svc_updateping(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error("CL_ParseServerMessage: svc_updateping >= cl.maxclients"); + cl.scores[i].qw_ping = MSG_ReadShort(&cl_message); +} + +static void Netmsg_svc_updatepl(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error("CL_ParseServerMessage: svc_updatepl >= cl.maxclients"); + cl.scores[i].qw_packetloss = MSG_ReadByte(&cl_message); +} + +static void Netmsg_svc_updateentertime(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i >= cl.maxclients) + Host_Error("CL_ParseServerMessage: svc_updateentertime >= cl.maxclients"); + // seconds ago + cl.scores[i].qw_entertime = cl.time - MSG_ReadFloat(&cl_message); +} + +static void Netmsg_svc_spawnbaseline(protocol_t *protocol) +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + if (i < 0 || i >= MAX_EDICTS) + Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); + if (i >= cl.max_entities) + CL_ExpandEntities(i); + CL_ParseBaseline(cl.entities + i, false); +} +static void Netmsg_svc_spawnstatic(protocol_t *protocol) +{ + CL_ParseStatic(false); +} +static void Netmsg_svc_temp_entity(protocol_t *protocol) +{ + if(!CL_VM_Parse_TempEntity()) + CL_ParseTempEntity (); +} + +static void Netmsg_svc_killedmonster(protocol_t *protocol) +{ + cl.stats[STAT_MONSTERS]++; +} + +static void Netmsg_svc_foundsecret(protocol_t *protocol) +{ + cl.stats[STAT_SECRETS]++; +} + +static void Netmsg_svc_updatestat(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i < 0 || i >= MAX_CL_STATS) + Host_Error ("svc_updatestat: %i is invalid", i); + cl.stats[i] = MSG_ReadByte(&cl_message); +} + +static void Netmsg_svc_updatestatlong(protocol_t *protocol) +{ + int i = MSG_ReadByte(&cl_message); + if (i < 0 || i >= MAX_CL_STATS) + Host_Error ("svc_updatestatlong: %i is invalid", i); + cl.stats[i] = MSG_ReadLong(&cl_message); +} + +static void Netmsg_svc_spawnstaticsound(protocol_t *protocol) +{ + CL_ParseStaticSound (false); +} + +static void Netmsg_svc_cdtrack(protocol_t *protocol) +{ + cl.cdtrack = cl.looptrack = MSG_ReadByte(&cl_message); +#ifdef CONFIG_CD + if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) + CDAudio_Play ((unsigned char)cls.forcetrack, true); + else + CDAudio_Play ((unsigned char)cl.cdtrack, true); +#endif +} + +static void Netmsg_svc_intermission(protocol_t *protocol) +{ + int i; + if(!cl.intermission) + cl.completed_time = cl.time; + cl.intermission = 1; + protocol->ReadVector(&cl_message, cl.qw_intermission_origin); + for (i = 0;i < 3;i++) + cl.qw_intermission_angles[i] = protocol->ReadAngle(&cl_message); +} + +static void Netmsg_svc_finale(protocol_t *protocol) +{ + if(!cl.intermission) + cl.completed_time = cl.time; + cl.intermission = 2; + SCR_CenterPrint(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); +} + +static void Netmsg_svc_sellscreen(protocol_t *protocol) +{ + Cmd_ExecuteString (&cmd_client, "help", src_local, true); +} + +static void Netmsg_svc_smallkick(protocol_t *protocol) +{ + cl.qw_weaponkick = -2; +} +static void Netmsg_svc_bigkick(protocol_t *protocol) +{ + cl.qw_weaponkick = -4; +} + +static void Netmsg_svc_muzzleflash(protocol_t *protocol) +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + // NOTE: in QW this only worked on clients + if (i < 0 || i >= MAX_EDICTS) + Host_Error("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); + if (i >= cl.max_entities) + CL_ExpandEntities(i); + cl.entities[i].persistent.muzzleflash = 1.0f; +} + +static void Netmsg_svc_updateuserinfo(protocol_t *protocol) +{ + QW_CL_UpdateUserInfo(); +} + +static void Netmsg_svc_setinfo(protocol_t *protocol) +{ + QW_CL_SetInfo(); +} + +static void Netmsg_svc_serverinfo(protocol_t *protocol) +{ + QW_CL_ServerInfo(); +} + +static void Netmsg_svc_download(protocol_t *protocol) +{ + QW_CL_ParseDownload(); +} + +static void Netmsg_svc_playerinfo(protocol_t *protocol) +{ + int i; + // slightly kill qw player entities now that we know there is + // an update of player entities this frame... + if (!cl.qwplayerupdatereceived) + { + cl.qwplayerupdatereceived = true; + for (i = 1;i < cl.maxclients;i++) + cl.entities_active[i] = false; + } + EntityStateQW_ReadPlayerUpdate(); +} + +static void Netmsg_svc_nails(protocol_t *protocol) +{ + QW_CL_ParseNails(); +} + +static void Netmsg_svc_chokecount(protocol_t *protocol) +{ + (void) MSG_ReadByte(&cl_message); + // FIXME: apply to netgraph + //for (j = 0;j < i;j++) + // cl.frames[(cls.netcon->qw.incoming_acknowledged-1-j)&QW_UPDATE_MASK].receivedtime = -2; +} + +static void Netmsg_svc_modellist(protocol_t *protocol) +{ + QW_CL_ParseModelList(); +} + +static void Netmsg_svc_soundlist(protocol_t *protocol) +{ + QW_CL_ParseSoundList(); +} + +static void Netmsg_svc_packetentities(protocol_t *protocol) +{ + EntityFrameQW_CL_ReadFrame(false); + // first update is the final signon stage + if (cls.signon == SIGNONS - 1) + { + cls.signon = SIGNONS; + CL_SignonReply (); + } +} + +static void Netmsg_svc_deltapacketentities(protocol_t *protocol) +{ + EntityFrameQW_CL_ReadFrame(true); + // first update is the final signon stage + if (cls.signon == SIGNONS - 1) + { + cls.signon = SIGNONS; + CL_SignonReply (); + } +} + +static void Netmsg_svc_maxspeed(protocol_t *protocol) +{ + cl.movevars_maxspeed = MSG_ReadFloat(&cl_message); +} + +static void Netmsg_svc_entgravity(protocol_t *protocol) +{ + cl.movevars_entgravity = MSG_ReadFloat(&cl_message); + if (!cl.movevars_entgravity) + cl.movevars_entgravity = 1.0f; +} + +static void Netmsg_svc_setpause(protocol_t *protocol) +{ + cl.paused = MSG_ReadByte(&cl_message) != 0; +#ifdef CONFIG_CD + if (cl.paused) + CDAudio_Pause (); + else + CDAudio_Resume (); +#endif + S_PauseGameSounds (cl.paused); +} \ No newline at end of file diff --git a/cl_protocol_dpp7.c b/cl_protocol_dpp7.c new file mode 100644 index 00000000..f019e014 --- /dev/null +++ b/cl_protocol_dpp7.c @@ -0,0 +1,7 @@ +#include "quakedef.h" +#include "cl_protocol_ext.h" + +protocol_netmsg_t netmsg_dpext_svc[] = +{ + NETMSG_DPEXT_SVC +}; \ No newline at end of file diff --git a/cl_protocol_ext.h b/cl_protocol_ext.h new file mode 100644 index 00000000..80d05fcb --- /dev/null +++ b/cl_protocol_ext.h @@ -0,0 +1,191 @@ +#include "cl_protocol_basenq.h" + +static void Netmsg_svc_showlmp (protocol_t *protocol) // [string] iconlabel [string] lmpfile [short] x [short] y +{ + if (gamemode == GAME_TENEBRAE) + { + // particle effect + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + (void) MSG_ReadByte(&cl_message); + MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + } + else + SHOWLMP_decodeshow(); +} + +static void Netmsg_svc_hidelmp (protocol_t *protocol) // [string] iconlabel +{ + if (gamemode == GAME_TENEBRAE) + { + // repeating particle effect + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + protocol->ReadCoord(&cl_message); + (void) MSG_ReadByte(&cl_message); + MSG_ReadLong(&cl_message); + MSG_ReadLong(&cl_message); + MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + } + else + SHOWLMP_decodehide(); +} + +static void Netmsg_svc_skybox (protocol_t *protocol) // [string] skyname +{ + R_SetSkyBox(MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring))); +} + +static void Netmsg_svc_downloaddata (protocol_t *protocol) // 50 // [int] start [short] size [variable length] data +{ + CL_ParseDownload(); +} + +static void Netmsg_svc_updatestatubyte (protocol_t *protocol) // 51 // [byte] stat [byte] value +{ + int i = MSG_ReadByte(&cl_message); + if (i < 0 || i >= MAX_CL_STATS) + Host_Error ("svc_updatestat: %i is invalid", i); + cl.stats[i] = MSG_ReadByte(&cl_message); +} + +static void Netmsg_svc_effect (protocol_t *protocol) // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate +{ + CL_ParseEffect (); +} + +static void Netmsg_svc_effect2 (protocol_t *protocol) // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate +{ + CL_ParseEffect2 (); +} + +// FIXME: Lazy +static void Netmsg_svc_precache (protocol_t *protocol) // 54 // short soundindex instead of byte +{ + if (protocol->num == PROTOCOL_DARKPLACES1 || protocol->num == PROTOCOL_DARKPLACES2 || protocol->num == PROTOCOL_DARKPLACES3) + { + // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6 + CL_ParseStartSoundPacket(true); + } + else + { + // was svc_sound2 in protocols 1, 2, 3, removed in 4, 5, changed to svc_precache in 6 + int i = (unsigned short)MSG_ReadShort(&cl_message); + char *s = MSG_ReadString(&cl_message, cl_readstring, sizeof(cl_readstring)); + if (i < 32768) + { + if (i >= 1 && i < MAX_MODELS) + { + dp_model_t *model = Mod_ForName(s, false, false, s[0] == '*' ? cl.model_name[1] : NULL); + if (!model) + Con_DPrintf("svc_precache: Mod_ForName(\"%s\") failed\n", s); + cl.model_precache[i] = model; + } + else + Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_MODELS); + } + else + { + i -= 32768; + if (i >= 1 && i < MAX_SOUNDS) + { + sfx_t *sfx = S_PrecacheSound (s, true, true); + if (!sfx && snd_initialized.integer) + Con_DPrintf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s); + cl.sound_precache[i] = sfx; + } + else + Con_Printf("svc_precache: index %i outside range %i...%i\n", i, 1, MAX_SOUNDS); + } + } +} + +static void Netmsg_svc_spawnbaseline2 (protocol_t *protocol) // 55 // short modelindex instead of byte +{ + int i = (unsigned short) MSG_ReadShort(&cl_message); + if (i < 0 || i >= MAX_EDICTS) + Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i); + if (i >= cl.max_entities) + CL_ExpandEntities(i); + CL_ParseBaseline (cl.entities + i, true); +} + +static void Netmsg_svc_spawnstatic2 (protocol_t *protocol) // 56 // short modelindex instead of byte +{ + CL_ParseStatic (true); +} + +static void Netmsg_svc_entities (protocol_t *protocol) // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata +{ + if (cls.signon == SIGNONS - 1) + { + // first update is the final signon stage + cls.signon = SIGNONS; + CL_SignonReply (); + } + if (protocol == &protocol_dpp1 || protocol == &protocol_dpp2 || protocol == &protocol_dpp3) + EntityFrame_CL_ReadFrame(); + else if (protocol == &protocol_dpp4) + EntityFrame4_CL_ReadFrame(); + else + EntityFrame5_CL_ReadFrame(); +} + +static void Netmsg_svc_csqcentities (protocol_t *protocol) // 58 // [short] entnum [variable length] entitydata ... [short] 0x0000 +{ + CSQC_ReadEntities(); +} + +static void Netmsg_svc_spawnstaticsound2 (protocol_t *protocol) // 59 // [coord3] [short] samp [byte] vol [byte] aten +{ + CL_ParseStaticSound (true); +} + +static void Netmsg_svc_trailparticles (protocol_t *protocol) // 60 // [short] entnum [short] effectnum [vector] start [vector] end +{ + CL_ParseTrailParticles(); +} + +static void Netmsg_svc_pointparticles (protocol_t *protocol) // 61 // [short] effectnum [vector] start [vector] velocity [short] count +{ + CL_ParsePointParticles(); +} + +static void Netmsg_svc_pointparticles1 (protocol_t *protocol) // 62 // [short] effectnum [vector] start, same as Netmsg_svc_pointparticles except velocity is zero and count is 1 +{ + CL_ParsePointParticles1(); +} +#define NETMSG_DPEXT_SVC \ + NETMSG_BASENQ_SVC, \ + {"svc_showlmp", Netmsg_svc_showlmp}, \ + {"svc_hidelmp", Netmsg_svc_hidelmp}, \ + {"svc_skybox", Netmsg_svc_skybox}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"", NULL}, \ + {"svc_downloaddata", Netmsg_svc_downloaddata}, \ + {"svc_updatestatubyte", Netmsg_svc_updatestatubyte}, \ + {"svc_effect", Netmsg_svc_effect}, \ + {"svc_effect2", Netmsg_svc_effect2}, \ + {"svc_sound2", Netmsg_svc_precache}, \ + {"svc_spawnbaseline2", Netmsg_svc_spawnbaseline2}, \ + {"svc_spawnstatic2", Netmsg_svc_spawnstatic2}, \ + {"svc_entities", Netmsg_svc_entities}, \ + {"svc_csqcentities", Netmsg_svc_csqcentities}, \ + {"svc_spawnstaticsound2", Netmsg_svc_spawnstaticsound2}, \ + {"svc_trailparticles", Netmsg_svc_trailparticles}, \ + {"svc_pointparticles", Netmsg_svc_pointparticles}, \ + {"svc_pointparticles1", Netmsg_svc_pointparticles1} diff --git a/cl_protocol_nq.c b/cl_protocol_nq.c new file mode 100644 index 00000000..8578d7cb --- /dev/null +++ b/cl_protocol_nq.c @@ -0,0 +1,8 @@ +#include "quakedef.h" +#include "protocol.h" +#include "cl_protocol_basenq.h" + +protocol_netmsg_t netmsg_nq_svc[] = +{ + NETMSG_BASENQ_SVC +}; diff --git a/cl_protocol_qw.c b/cl_protocol_qw.c new file mode 100644 index 00000000..28f1cb65 --- /dev/null +++ b/cl_protocol_qw.c @@ -0,0 +1,59 @@ +#include "cl_protocol_baseqw.h" + +protocol_netmsg_t netmsg_qw_svc[] = +{ + {"svc_bad", NULL}, // 0 + {"svc_nop", Netmsg_svc_nop}, // 1 + {"svc_disconnect", Netmsg_svc_disconnect}, // 2 + {"svc_updatestat", Netmsg_svc_updatestat}, // 3 // [byte] [byte] + {"", NULL}, // 4 + {"svc_setview", NULL}, // 5 // [short] entity number + {"svc_sound", Netmsg_svc_sound}, // 6 // + {"", NULL}, // 7 + {"svc_print", Netmsg_svc_print}, // 8 // [byte] id [string] null terminated string + {"svc_stufftext", Netmsg_svc_stufftext}, // 9 // [string] stuffed into client's console buffer + {"svc_setangle", Netmsg_svc_setangle}, // 10 // [angle3] set the view angle to this absolute value + {"svc_serverdata", Netmsg_svc_serverdata}, // 11 // [long] protocol ... + {"svc_lightstyle", Netmsg_svc_lightstyle}, // 12 // [byte] [string] + {"", NULL}, // 13 + {"svc_updatefrags", Netmsg_svc_updatefrags}, // 14 // [byte] [short] + {"", NULL}, // 15 + {"svc_stopsound", Netmsg_svc_stopsound}, // 16 // + {"", NULL}, // 17 + {"", NULL}, // 18 + {"svc_damage", Netmsg_svc_damage}, // 19 + {"svc_spawnstatic", Netmsg_svc_spawnstatic}, // 20 + {"", NULL}, // 21 + {"svc_spawnbaseline", Netmsg_svc_spawnbaseline}, // 22 + {"svc_temp_entity", Netmsg_svc_temp_entity}, // 23 // variable + {"svc_setpause", Netmsg_svc_setpause}, // 24 // [byte] on / off + {"", NULL}, // 25 + {"svc_centerprint", Netmsg_svc_centerprint}, // 26 // [string] to put in center of the screen + {"svc_killedmonster", Netmsg_svc_killedmonster}, // 27 + {"svc_foundsecret", Netmsg_svc_foundsecret}, // 28 + {"svc_spawnstaticsound", Netmsg_svc_spawnstaticsound}, // 29 // [coord3] [byte] samp [byte] vol [byte] aten + {"svc_intermission", Netmsg_svc_intermission}, // 30 // [vec3_t] origin [vec3_t] angle + {"svc_finale", Netmsg_svc_finale}, // 31 // [string] text + {"svc_cdtrack", Netmsg_svc_cdtrack}, // 32 // [byte] track + {"svc_sellscreen", Netmsg_svc_sellscreen}, // 33 + {"svc_smallkick", Netmsg_svc_smallkick}, // 34 // set client punchangle to 2 + {"svc_bigkick", Netmsg_svc_bigkick}, // 35 // set client punchangle to 4 + {"svc_updateping", Netmsg_svc_updateping}, // 36 // [byte] [short] + {"svc_updateentertime", Netmsg_svc_updateentertime}, // 37 // [byte] [float] + {"svc_updatestatlong", Netmsg_svc_updatestatlong}, // 38 // [byte] [long] + {"svc_muzzleflash", Netmsg_svc_muzzleflash}, // 39 // [short] entity + {"svc_updateuserinfo", Netmsg_svc_updateuserinfo}, // 40 // [byte] slot [long] uid + {"svc_download", Netmsg_svc_download}, // 41 // [short] size [size bytes] + {"svc_playerinfo", Netmsg_svc_playerinfo}, // 42 // variable + {"svc_nails", Netmsg_svc_nails}, // 43 // [byte] num [48 bits] xyzpy 12 12 12 4 8 + {"svc_chokecount", Netmsg_svc_chokecount}, // 44 // [byte] packets choked + {"svc_modellist", Netmsg_svc_modellist}, // 45 // [strings] + {"svc_soundlist", Netmsg_svc_soundlist}, // 46 // [strings] + {"svc_packetentities", Netmsg_svc_packetentities}, // 47 // [...] + {"svc_deltapacketentities", Netmsg_svc_deltapacketentities}, // 48 // [...] + {"svc_maxspeed", Netmsg_svc_maxspeed}, // 49 // maxspeed change, for prediction + {"svc_entgravity", Netmsg_svc_entgravity}, // 50 // gravity change, for prediction + {"svc_setinfo", Netmsg_svc_setinfo}, // 51 // setinfo on a client + {"svc_serverinfo", Netmsg_svc_serverinfo}, // 52 // serverinfo + {"svc_updatepl", Netmsg_svc_updatepl} // 53 // [byte] [byte] +}; diff --git a/cl_screen.c b/cl_screen.c index dfdd04a0..8d914975 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -523,7 +523,7 @@ static int SCR_DrawQWDownload(int offset) cls.qw_downloadspeedtime = host.realtime; cls.qw_downloadspeedcount = 0; } - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) dpsnprintf(temp, sizeof(temp), "Downloading %s %3i%% (%i) at %i bytes/s", cls.qw_downloadname, cls.qw_downloadpercent, cls.qw_downloadmemorycursize, cls.qw_downloadspeedrate); else dpsnprintf(temp, sizeof(temp), "Downloading %s %3i%% (%i/%i) at %i bytes/s", cls.qw_downloadname, cls.qw_downloadpercent, cls.qw_downloadmemorycursize, cls.qw_downloadmemorymaxsize, cls.qw_downloadspeedrate); diff --git a/client.h b/client.h index 1d124533..9c9295ba 100644 --- a/client.h +++ b/client.h @@ -863,7 +863,7 @@ typedef struct client_static_s lhnetaddress_t rcon_address; // protocol version of the server we're connected to // (kept outside client_state_t because it's used between levels) - protocolversion_t protocol; + protocol_t *protocol; #define MAX_RCONS 16 int rcon_trying; @@ -1452,6 +1452,8 @@ typedef struct client_state_s // used by EntityState5_ReadUpdate skeleton_t *engineskeletonobjects; + + qbool qwplayerupdatereceived; } client_state_t; diff --git a/clvm_cmds.c b/clvm_cmds.c index c8c8123b..36580888 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -1663,14 +1663,14 @@ static void VM_CL_ReadLong (prvm_prog_t *prog) static void VM_CL_ReadCoord (prvm_prog_t *prog) { VM_SAFEPARMCOUNT(0, VM_CL_ReadCoord); - PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadCoord(&cl_message, cls.protocol); + PRVM_G_FLOAT(OFS_RETURN) = cls.protocol->ReadCoord(&cl_message); } //#365 float() readangle (EXT_CSQC) static void VM_CL_ReadAngle (prvm_prog_t *prog) { VM_SAFEPARMCOUNT(0, VM_CL_ReadAngle); - PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadAngle(&cl_message, cls.protocol); + PRVM_G_FLOAT(OFS_RETURN) = cls.protocol->ReadAngle(&cl_message); } //#366 string() readstring (EXT_CSQC) diff --git a/com_msg.c b/com_msg.c index 0de4fc67..63d857f2 100644 --- a/com_msg.c +++ b/com_msg.c @@ -201,23 +201,25 @@ void MSG_WriteCoord32f (sizebuf_t *sb, float f) MSG_WriteFloat (sb, f); } -void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol) -{ - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD) - MSG_WriteCoord13i (sb, f); - else if (protocol == PROTOCOL_DARKPLACES1) - MSG_WriteCoord32f (sb, f); - else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4) - MSG_WriteCoord16i (sb, f); - else - MSG_WriteCoord32f (sb, f); +void MSG_WriteVector13i (sizebuf_t *sb, const vec3_t v) +{ + MSG_WriteCoord13i (sb, v[0]); + MSG_WriteCoord13i (sb, v[1]); + MSG_WriteCoord13i (sb, v[2]); +} + +void MSG_WriteVector16i (sizebuf_t *sb, const vec3_t v) +{ + MSG_WriteCoord16i (sb, v[0]); + MSG_WriteCoord16i (sb, v[1]); + MSG_WriteCoord16i (sb, v[2]); } -void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol) +void MSG_WriteVector32f (sizebuf_t *sb, const vec3_t v) { - MSG_WriteCoord (sb, v[0], protocol); - MSG_WriteCoord (sb, v[1], protocol); - MSG_WriteCoord (sb, v[2], protocol); + MSG_WriteCoord32f (sb, v[0]); + MSG_WriteCoord32f (sb, v[1]); + MSG_WriteCoord32f (sb, v[2]); } // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem @@ -242,14 +244,6 @@ void MSG_WriteAngle32f (sizebuf_t *sb, float f) MSG_WriteFloat (sb, f); } -void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol) -{ - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD) - MSG_WriteAngle8i (sb, f); - else - MSG_WriteAngle16i (sb, f); -} - // // reading functions // @@ -381,23 +375,25 @@ float MSG_ReadCoord32f (sizebuf_t *sb) return MSG_ReadLittleFloat(sb); } -float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol) +void MSG_ReadVector13i (sizebuf_t *sb, vec3_t v) { - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD) - return MSG_ReadCoord13i(sb); - else if (protocol == PROTOCOL_DARKPLACES1) - return MSG_ReadCoord32f(sb); - else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4) - return MSG_ReadCoord16i(sb); - else - return MSG_ReadCoord32f(sb); + v[0] = MSG_ReadCoord13i(sb); + v[1] = MSG_ReadCoord13i(sb); + v[2] = MSG_ReadCoord13i(sb); } -void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol) +void MSG_ReadVector16i (sizebuf_t *sb, vec3_t v) { - v[0] = MSG_ReadCoord(sb, protocol); - v[1] = MSG_ReadCoord(sb, protocol); - v[2] = MSG_ReadCoord(sb, protocol); + v[0] = MSG_ReadCoord16i(sb); + v[1] = MSG_ReadCoord16i(sb); + v[2] = MSG_ReadCoord16i(sb); +} + +void MSG_ReadVector32f (sizebuf_t *sb, vec3_t v) +{ + v[0] = MSG_ReadCoord32f(sb); + v[1] = MSG_ReadCoord32f(sb); + v[2] = MSG_ReadCoord32f(sb); } // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem @@ -414,12 +410,4 @@ float MSG_ReadAngle16i (sizebuf_t *sb) float MSG_ReadAngle32f (sizebuf_t *sb) { return MSG_ReadFloat (sb); -} - -float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol) -{ - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD) - return MSG_ReadAngle8i (sb); - else - return MSG_ReadAngle16i (sb); -} +} \ No newline at end of file diff --git a/common.h b/common.h index d11b141c..11e444ee 100644 --- a/common.h +++ b/common.h @@ -121,28 +121,6 @@ void StoreLittleShort (unsigned char *buffer, unsigned short i); //============================================================================ -// these versions are purely for internal use, never sent in network protocol -// (use Protocol_EnumForNumber and Protocol_NumberToEnum to convert) -typedef enum protocolversion_e -{ - PROTOCOL_UNKNOWN, - PROTOCOL_DARKPLACES7, ///< added QuakeWorld-style movement protocol to allow more consistent prediction - PROTOCOL_DARKPLACES6, ///< various changes - PROTOCOL_DARKPLACES5, ///< uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at http://www.garagegames.com/articles/networking1/ - PROTOCOL_DARKPLACES4, ///< various changes - PROTOCOL_DARKPLACES3, ///< uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snapshot updates on a QuakeWorld-like protocol, but it is broken and impossible to fix - PROTOCOL_DARKPLACES2, ///< various changes - PROTOCOL_DARKPLACES1, ///< uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta compression method - PROTOCOL_QUAKEDP, ///< darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as no extended features are used - PROTOCOL_NEHAHRAMOVIE, ///< Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but only ever used by neh_gl.exe), this is potentially backwards compatible with quake protocol as long as no extended features are used (but in actuality the neh_gl.exe which wrote this protocol ALWAYS wrote the extended information) - PROTOCOL_QUAKE, ///< quake (aka netquake/normalquake/nq) protocol - PROTOCOL_QUAKEWORLD, ///< quakeworld protocol - PROTOCOL_NEHAHRABJP, ///< same as QUAKEDP but with 16bit modelindex - PROTOCOL_NEHAHRABJP2, ///< same as NEHAHRABJP but with 16bit soundindex - PROTOCOL_NEHAHRABJP3 ///< same as NEHAHRABJP2 but with some changes -} -protocolversion_t; - /*! \name Message IO functions. * Handles byte ordering and avoids alignment errors * @{ @@ -162,9 +140,9 @@ void MSG_WriteAngle32f (sizebuf_t *sb, vec_t f); void MSG_WriteCoord13i (sizebuf_t *sb, vec_t f); void MSG_WriteCoord16i (sizebuf_t *sb, vec_t f); void MSG_WriteCoord32f (sizebuf_t *sb, vec_t f); -void MSG_WriteCoord (sizebuf_t *sb, vec_t f, protocolversion_t protocol); -void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol); -void MSG_WriteAngle (sizebuf_t *sb, vec_t f, protocolversion_t protocol); +void MSG_WriteVector13i (sizebuf_t *sb, const vec3_t v); +void MSG_WriteVector16i (sizebuf_t *sb, const vec3_t v); +void MSG_WriteVector32f (sizebuf_t *sb, const vec3_t v); void MSG_BeginReading (sizebuf_t *sb); int MSG_ReadLittleShort (sizebuf_t *sb); @@ -188,9 +166,9 @@ float MSG_ReadAngle32f (sizebuf_t *sb); float MSG_ReadCoord13i (sizebuf_t *sb); float MSG_ReadCoord16i (sizebuf_t *sb); float MSG_ReadCoord32f (sizebuf_t *sb); -float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol); -void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol); -float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol); +void MSG_ReadVector13i (sizebuf_t *sb, vec3_t v); +void MSG_ReadVector16i (sizebuf_t *sb, vec3_t v); +void MSG_ReadVector32f (sizebuf_t *sb, vec3_t v); //@} //============================================================================ diff --git a/csprogs.c b/csprogs.c index 21453fae..456b1b14 100644 --- a/csprogs.c +++ b/csprogs.c @@ -401,7 +401,7 @@ qbool CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum) && (entrender->alpha >= 1) && !(renderflags & RF_NOSHADOW) && !(entrender->flags & RENDER_VIEWMODEL) - && (!(entrender->flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) + && (!(entrender->flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != &protocol_nehahramovie && !cl_noplayershadow.integer))) entrender->flags |= RENDER_SHADOW; if (entrender->flags & RENDER_VIEWMODEL) entrender->flags |= RENDER_NOSELFSHADOW; @@ -1102,7 +1102,7 @@ void CL_VM_Init (void) i = 0; CL_CutDemo(&demobuf, &demofilesize); - while(MakeDownloadPacket(csqc_progname.string, csprogsdata, (size_t)csprogsdatasize, csprogsdatacrc, i++, &sb, cls.protocol)) + while(MakeDownloadPacket(csqc_progname.string, csprogsdata, (size_t)csprogsdatasize, csprogsdatacrc, i++, &sb, cls.protocol->num)) CL_WriteDemoMessage(&sb); CL_PasteDemo(&demobuf, &demofilesize); diff --git a/gl_rmain.c b/gl_rmain.c index 4e76b895..13e25c76 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -6975,7 +6975,7 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qbool wantnormals, qboo rsurface.skeleton = ent->skeleton; memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param)); rsurface.ent_skinnum = ent->skinnum; - rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; + rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == &protocol_quakeworld && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1; rsurface.ent_flags = ent->flags; if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit)) rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT; diff --git a/makefile.inc b/makefile.inc index 20c6ec3c..7df34688 100644 --- a/makefile.inc +++ b/makefile.inc @@ -91,6 +91,9 @@ OBJ_COMMON= \ cl_main.o \ cl_parse.o \ cl_particles.o \ + cl_protocol_dpp7.o \ + cl_protocol_nq.o \ + cl_protocol_qw.o \ cl_screen.o \ cl_video.o \ cl_video_libavw.o \ @@ -162,6 +165,7 @@ OBJ_COMMON= \ sv_main.o \ sv_move.o \ sv_phys.o \ + sv_protocol.o \ sv_save.o \ sv_send.o \ sv_user.o \ diff --git a/mvm_cmds.c b/mvm_cmds.c index a8fdbb6e..ee92c2f5 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -748,13 +748,13 @@ static void VM_M_WriteLong (prvm_prog_t *prog) static void VM_M_WriteAngle (prvm_prog_t *prog) { VM_SAFEPARMCOUNT(1, VM_M_WriteAngle); - MSG_WriteAngle (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); + sv.protocol->WriteAngle (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0)); } static void VM_M_WriteCoord (prvm_prog_t *prog) { VM_SAFEPARMCOUNT(1, VM_M_WriteCoord); - MSG_WriteCoord (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0), sv.protocol); + sv.protocol->WriteCoord(VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0)); } static void VM_M_WriteString (prvm_prog_t *prog) diff --git a/netconn.c b/netconn.c index f406012d..639072a8 100755 --- a/netconn.c +++ b/netconn.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "protocol.h" #include "thread.h" #include "lhnet.h" @@ -723,7 +724,7 @@ static int NetConn_AddCryptoFlag(crypto_t *crypto) return flag; } -int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qbool quakesignon_suppressreliables) +int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocol_t *protocol, int rate, int burstsize, qbool quakesignon_suppressreliables) { int totallen = 0; unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE]; @@ -737,7 +738,7 @@ int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocolversion_t protoco conn->outgoing_netgraph[conn->outgoing_packetcounter].cleartime = conn->cleartime; - if (protocol == PROTOCOL_QUAKEWORLD) + if (protocol == &protocol_quakeworld) { int packetLen; qbool sendreliable; @@ -1195,7 +1196,7 @@ void NetConn_UpdateSockets(void) } } -static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, size_t length, protocolversion_t protocol, double newtimeout) +static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, size_t length, protocol_t *protocol, double newtimeout) { int originallength = (int)length; unsigned char sendbuffer[NET_HEADERSIZE+NET_MAXMESSAGE]; @@ -1204,7 +1205,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s if (length < 8) return 0; - if (protocol == PROTOCOL_QUAKEWORLD) + if (protocol == &protocol_quakeworld) { unsigned int sequence, sequence_ack; qbool reliable_ack, reliable_message; @@ -1505,7 +1506,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s return 0; } -static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocolversion_t initialprotocol) +static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, protocol_t *initialprotocol) { crypto_t *crypto; cls.connect_trying = false; @@ -1547,9 +1548,9 @@ static void NetConn_ConnectionEstablished(lhnetsocket_t *mysocket, lhnetaddress_ cls.protocol = initialprotocol; // reset move sequence numbering on this new connection cls.servermovesequence = 0; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) CL_ForwardToServer("new"); - if (cls.protocol == PROTOCOL_QUAKE) + if (cls.protocol == &protocol_netquake) { // write a keepalive (clc_nop) as it seems to greatly improve the // chances of connecting to a netquake server @@ -1769,7 +1770,7 @@ static void NetConn_ClientParsePacket_ServerList_ParseDPList(lhnetaddress_t *sen if (serverlist_consoleoutput && developer_networking.integer) Con_Printf("Requesting info from DarkPlaces server %s\n", ipstring); - if( !NetConn_ClientParsePacket_ServerList_PrepareQuery( PROTOCOL_DARKPLACES7, ipstring, false ) ) { + if( !NetConn_ClientParsePacket_ServerList_PrepareQuery( protocol_dpp7.num, ipstring, false ) ) { break; } @@ -1927,7 +1928,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat #ifdef CONFIG_MENU M_Update_Return_Reason("Accepted"); #endif - NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_DARKPLACES3); + NetConn_ConnectionEstablished(mysocket, peeraddress, &protocol_dpp3); return true; } if (length > 7 && !memcmp(string, "reject ", 7) && cls.connect_trying) @@ -2073,7 +2074,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat if (serverlist_consoleoutput && developer_networking.integer) Con_Printf("Requesting info from QuakeWorld server %s\n", ipstring); - if( !NetConn_ClientParsePacket_ServerList_PrepareQuery( PROTOCOL_QUAKEWORLD, ipstring, false ) ) { + if( !NetConn_ClientParsePacket_ServerList_PrepareQuery( protocol_quakeworld.num, ipstring, false ) ) { break; } @@ -2136,7 +2137,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat #ifdef CONFIG_MENU M_Update_Return_Reason("QuakeWorld Accepted"); #endif - NetConn_ConnectionEstablished(mysocket, peeraddress, PROTOCOL_QUAKEWORLD); + NetConn_ConnectionEstablished(mysocket, peeraddress, &protocol_quakeworld); return true; } if (length > 2 && !memcmp(string, "n\\", 2)) @@ -2202,7 +2203,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat return true; } // quakeworld ingame packet - if (fromserver && cls.protocol == PROTOCOL_QUAKEWORLD && length >= 8 && (ret = NetConn_ReceivedMessage(cls.netcon, data, length, cls.protocol, net_messagetimeout.value)) == 2) + if (fromserver && cls.protocol == &protocol_quakeworld && length >= 8 && (ret = NetConn_ReceivedMessage(cls.netcon, data, length, cls.protocol, net_messagetimeout.value)) == 2) { ret = 0; CL_ParseServerMessage(); @@ -2256,7 +2257,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat #ifdef CONFIG_MENU M_Update_Return_Reason("Accepted"); #endif - NetConn_ConnectionEstablished(mysocket, &clientportaddress, PROTOCOL_QUAKE); + NetConn_ConnectionEstablished(mysocket, &clientportaddress, &protocol_netquake); } break; case CCREP_REJECT: @@ -3316,7 +3317,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat // protocol // (this protects more modern protocols against being used for // Quake packet flood Denial Of Service attacks) - if (length >= 5 && (i = BuffBigLong(data)) && (i & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (i & NETFLAG_LENGTH_MASK) == length && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3) && !ENCRYPTION_REQUIRED) + if (length >= 5 && (i = BuffBigLong(data)) && (i & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (i & NETFLAG_LENGTH_MASK) == length && (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3 || sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3) && !ENCRYPTION_REQUIRED) { int c; int protocolnumber; @@ -3697,7 +3698,7 @@ void NetConn_QueryMasters(qbool querydp, qbool queryqw) if(LHNETADDRESS_GetAddressType(&favorites[j]) == af) { if(LHNETADDRESS_ToString(&favorites[j], request, sizeof(request), true)) - NetConn_ClientParsePacket_ServerList_PrepareQuery( PROTOCOL_DARKPLACES7, request, true ); + NetConn_ClientParsePacket_ServerList_PrepareQuery( protocol_dpp7.num, request, true ); } } } @@ -3747,7 +3748,7 @@ void NetConn_QueryMasters(qbool querydp, qbool queryqw) if(LHNETADDRESS_ToString(&favorites[j], request, sizeof(request), true)) { NetConn_WriteString(cl_sockets[i], "\377\377\377\377status\n", &favorites[j]); - NetConn_ClientParsePacket_ServerList_PrepareQuery( PROTOCOL_QUAKEWORLD, request, true ); + NetConn_ClientParsePacket_ServerList_PrepareQuery( protocol_quakeworld.num, request, true ); } } } @@ -3803,7 +3804,7 @@ static void Net_Heartbeat_f(cmd_state_t *cmd) static void PrintStats(netconn_t *conn) { - if ((cls.state == ca_connected && cls.protocol == PROTOCOL_QUAKEWORLD) || (sv.active && sv.protocol == PROTOCOL_QUAKEWORLD)) + if ((cls.state == ca_connected && cls.protocol == &protocol_quakeworld) || (sv.active && sv.protocol == &protocol_quakeworld)) Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->outgoing_unreliable_sequence, conn->qw.incoming_sequence); else Con_Printf("address=%21s canSend=%u sendSeq=%6u recvSeq=%6u\n", conn->address, !conn->sendMessageLength, conn->nq.sendSequence, conn->nq.receiveSequence); diff --git a/netconn.h b/netconn.h index ceba2e3e..c36682d2 100755 --- a/netconn.h +++ b/netconn.h @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define NET_H #include "lhnet.h" +#include "protocol.h" #define NET_HEADERSIZE (2 * sizeof(unsigned int)) @@ -431,7 +432,7 @@ extern cvar_t net_usesizelimit; extern cvar_t net_burstreserve; qbool NetConn_CanSend(netconn_t *conn); -int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocolversion_t protocol, int rate, int burstsize, qbool quakesignon_suppressreliables); +int NetConn_Transmit(netconn_t *conn, sizebuf_t *data, protocol_t *protocol, int rate, int burstsize, qbool quakesignon_suppressreliables); qbool NetConn_HaveClientPorts(void); qbool NetConn_HaveServerPorts(void); void NetConn_CloseClientPorts(void); diff --git a/protocol.c b/protocol.c index 8bdb0051..f0a6917c 100644 --- a/protocol.c +++ b/protocol.c @@ -39,80 +39,249 @@ entity_state_t defaultstate = // LadyHavoc: I own protocol ranges 96, 97, 3500-3599 -struct protocolversioninfo_s +protocol_t protocol_netquake = { - int number; - protocolversion_t version; - const char *name; -} -protocolversioninfo[] = -{ - { 3504, PROTOCOL_DARKPLACES7 , "DP7"}, - { 3503, PROTOCOL_DARKPLACES6 , "DP6"}, - { 3502, PROTOCOL_DARKPLACES5 , "DP5"}, - { 3501, PROTOCOL_DARKPLACES4 , "DP4"}, - { 3500, PROTOCOL_DARKPLACES3 , "DP3"}, - { 97, PROTOCOL_DARKPLACES2 , "DP2"}, - { 96, PROTOCOL_DARKPLACES1 , "DP1"}, - { 15, PROTOCOL_QUAKEDP , "QUAKEDP"}, - { 15, PROTOCOL_QUAKE , "QUAKE"}, - { 28, PROTOCOL_QUAKEWORLD , "QW"}, - { 250, PROTOCOL_NEHAHRAMOVIE, "NEHAHRAMOVIE"}, - {10000, PROTOCOL_NEHAHRABJP , "NEHAHRABJP"}, - {10001, PROTOCOL_NEHAHRABJP2 , "NEHAHRABJP2"}, - {10002, PROTOCOL_NEHAHRABJP3 , "NEHAHRABJP3"}, - { 0, PROTOCOL_UNKNOWN , NULL} -}; - -protocolversion_t Protocol_EnumForName(const char *s) + .name = "QUAKE", + .num = 15, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 34, + .svcmsg = netmsg_nq_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_quakedp = { - int i; - for (i = 0;protocolversioninfo[i].name;i++) - if (!strcasecmp(s, protocolversioninfo[i].name)) - return protocolversioninfo[i].version; - return PROTOCOL_UNKNOWN; -} + .name = "QUAKEDP", + .num = 15, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; -const char *Protocol_NameForEnum(protocolversion_t p) +protocol_t protocol_quakeworld = { - int i; - for (i = 0;protocolversioninfo[i].name;i++) - if (protocolversioninfo[i].version == p) - return protocolversioninfo[i].name; - return "UNKNOWN"; -} + .name = "QW", + .num = 28, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 53, + .svcmsg = netmsg_qw_svc, + .max_clcmsg = 59, + .clcmsg = NULL +}; -protocolversion_t Protocol_EnumForNumber(int n) +protocol_t protocol_dpp1 = { - int i; - for (i = 0;protocolversioninfo[i].name;i++) - if (protocolversioninfo[i].number == n) - return protocolversioninfo[i].version; - return PROTOCOL_UNKNOWN; -} + .name = "DP1", + .num = 96, + .WriteCoord = MSG_WriteCoord32f, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector32f, + .ReadCoord = MSG_ReadCoord32f, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector32f, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; -int Protocol_NumberForEnum(protocolversion_t p) +protocol_t protocol_dpp2 = { - int i; - for (i = 0;protocolversioninfo[i].name;i++) - if (protocolversioninfo[i].version == p) - return protocolversioninfo[i].number; - return 0; -} + .name = "DP2", + .num = 97, + .WriteCoord = MSG_WriteCoord16i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector16i, + .ReadCoord = MSG_ReadCoord16i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector16i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; -void Protocol_Names(char *buffer, size_t buffersize) +protocol_t protocol_dpp3 = { - int i; - if (buffersize < 1) - return; - buffer[0] = 0; - for (i = 0;protocolversioninfo[i].name;i++) - { - if (i > 1) - strlcat(buffer, " ", buffersize); - strlcat(buffer, protocolversioninfo[i].name, buffersize); - } -} + .name = "DP3", + .num = 3500, + .WriteCoord = MSG_WriteCoord16i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector16i, + .ReadCoord = MSG_ReadCoord16i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector16i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_dpp4 = +{ + .name = "DP4", + .num = 3501, + .WriteCoord = MSG_WriteCoord16i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector16i, + .ReadCoord = MSG_ReadCoord16i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector16i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_dpp5 = +{ + .name = "DP5", + .num = 3502, + .WriteCoord = MSG_WriteCoord32f, + .WriteAngle = MSG_WriteAngle16i, + .WriteVector = MSG_WriteVector32f, + .ReadCoord = MSG_ReadCoord32f, + .ReadAngle = MSG_ReadAngle16i, + .ReadVector = MSG_ReadVector32f, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_dpp6 = +{ + .name = "DP6", + .num = 3503, + .WriteCoord = MSG_WriteCoord32f, + .WriteAngle = MSG_WriteAngle16i, + .WriteVector = MSG_WriteVector32f, + .ReadCoord = MSG_ReadCoord32f, + .ReadAngle = MSG_ReadAngle16i, + .ReadVector = MSG_ReadVector32f, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_dpp7 = +{ + .name = "DP7", + .num = 3504, + .WriteCoord = MSG_WriteCoord32f, + .WriteAngle = MSG_WriteAngle16i, + .WriteVector = MSG_WriteVector32f, + .ReadCoord = MSG_ReadCoord32f, + .ReadAngle = MSG_ReadAngle16i, + .ReadVector = MSG_ReadVector32f, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc + +}; + +protocol_t protocol_nehahramovie = +{ + .name = "NEHAHRAMOVIE", + .num = 250, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_nehahrabjp = +{ + .name = "NEHAHRABJP", + .num = 10000, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_nehahrabjp2 = +{ + .name = "NEHAHRABJP2", + .num = 10001, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t protocol_nehahrabjp3 = +{ + .name = "NEHAHRABJP3", + .num = 10002, + .WriteCoord = MSG_WriteCoord13i, + .WriteAngle = MSG_WriteAngle8i, + .WriteVector = MSG_WriteVector13i, + .ReadCoord = MSG_ReadCoord13i, + .ReadAngle = MSG_ReadAngle8i, + .ReadVector = MSG_ReadVector13i, + .max_svcmsg = 62, + .svcmsg = netmsg_dpext_svc, + .max_clcmsg = 59, + .clcmsg = netmsg_base_clc +}; + +protocol_t *protocols[] = +{ + &protocol_netquake, + &protocol_quakedp, + &protocol_quakeworld, + &protocol_dpp1, + &protocol_dpp2, + &protocol_dpp3, + &protocol_dpp4, + &protocol_dpp5, + &protocol_dpp6, + &protocol_dpp7, + &protocol_nehahramovie, + &protocol_nehahrabjp, + &protocol_nehahrabjp2, + &protocol_nehahrabjp3, + NULL +}; void Protocol_UpdateClientStats(const int *stats) { @@ -147,6 +316,42 @@ STAT_VIEWZOOM, // this rarely changes -1, }; +protocol_t *Protocol_ForName(const char *name) +{ + int i; + for(i = 0; &protocols[i]; i++) + { + if(!strncmp(name, protocols[i]->name, strlen(protocols[i]->name))) + break; + } + return protocols[i]; +} + +protocol_t *Protocol_ForNumber(int num) +{ + int i; + for(i = 0; &protocols[i]; i++) + { + if(protocols[i]->num == num) + break; + } + return protocols[i]; +} + +void Protocol_Names(char *buffer, size_t buffersize) +{ + int i; + if (buffersize < 1) + return; + buffer[0] = 0; + for (i = 0; protocols[i]; i++) + { + if (i > 1) + strlcat(buffer, " ", buffersize); + strlcat(buffer, protocols[i]->name, buffersize); + } +} + void Protocol_WriteStatsReliable(void) { int i, j; @@ -165,7 +370,7 @@ void Protocol_WriteStatsReliable(void) { host_client->statsdeltabits[i >> 3] -= (1 << (i & 7)); // send the stat as a byte if possible - if (sv.protocol == PROTOCOL_QUAKEWORLD) + if (sv.protocol == &protocol_quakeworld) { if (host_client->stats[i] >= 0 && host_client->stats[i] < 256) { diff --git a/protocol.h b/protocol.h index 3fa39244..3df4f28e 100644 --- a/protocol.h +++ b/protocol.h @@ -22,12 +22,81 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef PROTOCOL_H #define PROTOCOL_H -// protocolversion_t is defined in common.h - -protocolversion_t Protocol_EnumForName(const char *s); -const char *Protocol_NameForEnum(protocolversion_t p); -protocolversion_t Protocol_EnumForNumber(int n); -int Protocol_NumberForEnum(protocolversion_t p); +enum +{ + PROTOCOL_UNKNOWN, + PROTOCOL_QUAKE = 15, ///< quake (aka netquake/normalquake/nq) protocol + PROTOCOL_QUAKEDP = 15, ///< darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as no extended features are used + PROTOCOL_QUAKEWORLD = 28, ///< quakeworld protocol + PROTOCOL_DARKPLACES1 = 96, ///< uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta compression method + PROTOCOL_DARKPLACES2 = 97, ///< various changes + PROTOCOL_NEHAHRAMOVIE = 250, ///< Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but only ever used by neh_gl.exe), this is potentially backwards compatible with quake protocol as long as no extended features are used (but in actuality the neh_gl.exe which wrote this protocol ALWAYS wrote the extended information) + PROTOCOL_DARKPLACES3 = 3500, ///< uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snapshot updates on a QuakeWorld-like protocol, but it is broken and impossible to fix + PROTOCOL_DARKPLACES4 = 3501, ///< various changes + PROTOCOL_DARKPLACES5 = 3502, ///< uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at http://www.garagegames.com/articles/networking1/ + PROTOCOL_DARKPLACES6 = 3503, ///< various changes + PROTOCOL_DARKPLACES7 = 3504, ///< added QuakeWorld-style movement protocol to allow more consistent prediction + PROTOCOL_NEHAHRABJP = 10000, ///< same as QUAKEDP but with 16bit modelindex + PROTOCOL_NEHAHRABJP2 = 10001, ///< same as NEHAHRABJP but with 16bit soundindex + PROTOCOL_NEHAHRABJP3 = 10002 ///< same as NEHAHRABJP2 but with some changes +}; + +typedef struct protocol_netmsg_s protocol_netmsg_t; +typedef struct protocol_s protocol_t; + +struct protocol_s +{ + const char *name; + const int num; + + void (*WriteCoord)(sizebuf_t *, float); + void (*WriteAngle)(sizebuf_t *, float); + void (*WriteVector)(sizebuf_t *, const vec3_t); + float (*ReadCoord)(sizebuf_t *); + float (*ReadAngle)(sizebuf_t *); + void (*ReadVector)(sizebuf_t *, vec3_t); + + // TODO: Other info? + const int max_svcmsg; + struct protocol_netmsg_s *svcmsg; + const int max_clcmsg; + struct protocol_netmsg_s *clcmsg; +}; + +struct protocol_netmsg_s +{ + const char *name; + void (*func)(struct protocol_s *); +}; + +typedef struct protocol_s protocol_t; +typedef struct protocol_netmsg_s protocol_netmsg_t; + +extern protocol_t protocol_netquake; +extern protocol_t protocol_quakedp; +extern protocol_t protocol_quakeworld; +extern protocol_t protocol_dpp1; +extern protocol_t protocol_dpp2; +extern protocol_t protocol_dpp3; +extern protocol_t protocol_dpp4; +extern protocol_t protocol_dpp5; +extern protocol_t protocol_dpp6; +extern protocol_t protocol_dpp7; +extern protocol_t protocol_nehahramovie; +extern protocol_t protocol_nehahrabjp; +extern protocol_t protocol_nehahrabjp2; +extern protocol_t protocol_nehahrabjp3; + +extern protocol_netmsg_t netmsg_nq_svc[]; +extern protocol_netmsg_t netmsg_qw_svc[]; +extern protocol_netmsg_t netmsg_dpext_svc[]; +extern protocol_netmsg_t netmsg_base_clc[]; + +#define PF_PREDICTION (1<<0) +#define PF_MOVE_CROUCH (1<<1) + +protocol_t *Protocol_ForName(const char *name); +protocol_t *Protocol_ForNumber(int num); void Protocol_Names(char *buffer, size_t buffersize); #define ENTITYSIZEPROFILING_START(msg, num, flags) \ @@ -278,9 +347,12 @@ void Protocol_Names(char *buffer, size_t buffersize); // #define clc_bad 0 #define clc_nop 1 -#define clc_disconnect 2 -#define clc_move 3 // [usercmd_t] +#define clc_disconnect 2 // (NETQUAKE) +#define clc_move 3 // [usercmd_t] #define clc_stringcmd 4 // [string] message +#define clc_delta 5 // (QUAKEWORLD) [byte] sequence number, requests delta compression of message +#define clc_tmove 6 // (QUAKEWORLD) teleport request, spectator only +#define clc_upload 7 // (QUAKEWORLD) teleport request, spectator only // LadyHavoc: my clc_ range, 50-59 #define clc_ackframe 50 // [int] framenumber @@ -453,7 +525,7 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co void EntityFrameQuake_ISeeDeadEntities(void); /* -PROTOCOL_DARKPLACES3 +&protocol_dpp3 server updates entities according to some (unmentioned) scheme. a frame consists of all visible entities, some of which are up to date, @@ -485,7 +557,7 @@ if server receives ack message in put packet it performs these steps: */ /* -PROTOCOL_DARKPLACES4 +&protocol_dpp4 a frame consists of some visible entities in a range (this is stored as start and end, note that end may be less than start if it wrapped). these entities are stored in a range (firstentity/endentity) of structs in the entitydata[] buffer. @@ -906,15 +978,7 @@ extern cvar_t developer_networkentities; #define qw_svc_setinfo 51 // setinfo on a client #define qw_svc_serverinfo 52 // serverinfo #define qw_svc_updatepl 53 // [byte] [byte] -// QUAKEWORLD -// client to server -#define qw_clc_bad 0 -#define qw_clc_nop 1 -#define qw_clc_move 3 // [[usercmd_t] -#define qw_clc_stringcmd 4 // [string] message -#define qw_clc_delta 5 // [byte] sequence number, requests delta compression of message -#define qw_clc_tmove 6 // teleport request, spectator only -#define qw_clc_upload 7 // teleport request, spectator only + // QUAKEWORLD // playerinfo flags from server // playerinfo always sends: playernum, flags, origin[] and framenumber diff --git a/sbar.c b/sbar.c index 6fc6c327..5c583564 100644 --- a/sbar.c +++ b/sbar.c @@ -1809,7 +1809,7 @@ static float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y) if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15)) myself = true; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { if (s->qw_spectator) { @@ -1874,12 +1874,12 @@ void Sbar_DeathmatchOverlay (void) if (cl.last_ping_request < host.realtime - 2 && cls.netcon) { cl.last_ping_request = host.realtime; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteByte(&cls.netcon->message, clc_stringcmd); MSG_WriteString(&cls.netcon->message, "pings"); } - else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6/* || cls.protocol == PROTOCOL_DARKPLACES7*/) + else if (cls.protocol == &protocol_netquake || cls.protocol == &protocol_quakedp || cls.protocol == &protocol_nehahramovie || cls.protocol == &protocol_nehahrabjp || cls.protocol == &protocol_nehahrabjp2 || cls.protocol == &protocol_nehahrabjp3 || cls.protocol == &protocol_dpp1 || cls.protocol == &protocol_dpp2 || cls.protocol == &protocol_dpp3 || cls.protocol == &protocol_dpp4 || cls.protocol == &protocol_dpp5 || cls.protocol == &protocol_dpp6/* || cls.protocol == &protocol_dpp7*/) { // these servers usually lack the pings command and so a less efficient "ping" command must be sent, which on modern DP servers will also reply with a pingplreport command after the ping listing static int ping_anyway_counter = 0; @@ -1911,7 +1911,7 @@ void Sbar_DeathmatchOverlay (void) ymin = 8; ymax = 40 + 8 + (Sbar_IsTeammatch() ? (teamlines * 8 + 5): 0) + scoreboardlines * 8 - 1; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) xmin = (int) (vid_conwidth.integer - (26 + 15) * 8 * FONT_SBAR->maxwidth) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't) else xmin = (int) (vid_conwidth.integer - (16 + 25) * 8 * FONT_SBAR->maxwidth) / 2; // 16 characters until name, then we assume 25 character names (they can be longer but usually aren't) @@ -1924,7 +1924,7 @@ void Sbar_DeathmatchOverlay (void) // draw the text y = 40; - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) { DrawQ_String(xmin, y, va(vabuf, sizeof(vabuf), "ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR ); } diff --git a/server.h b/server.h index b3ab98a2..f6b5b5f8 100644 --- a/server.h +++ b/server.h @@ -85,7 +85,7 @@ typedef struct server_s qbool loadgame; /// one of the PROTOCOL_ values - protocolversion_t protocol; + protocol_t *protocol; double time; diff --git a/snd_main.c b/snd_main.c index aab18140..6933c16e 100644 --- a/snd_main.c +++ b/snd_main.c @@ -1566,7 +1566,7 @@ static void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int // If it's a static sound if (isstatic) { - if (sfx->loopstart >= sfx->total_length && (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEWORLD)) + if (sfx->loopstart >= sfx->total_length && (cls.protocol == &protocol_netquake || cls.protocol == &protocol_quakeworld)) Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name); target_chan->distfade = attenuation / (64.0f * snd_soundradius.value); } diff --git a/sv_ccmds.c b/sv_ccmds.c index 27847ffb..9740c437 100644 --- a/sv_ccmds.c +++ b/sv_ccmds.c @@ -674,7 +674,7 @@ static void SV_Pings_f(cmd_state_t *cmd) if (!host_client->netconnection) return; - if (sv.protocol != PROTOCOL_QUAKEWORLD) + if (sv.protocol != &protocol_quakeworld) { MSG_WriteByte(&host_client->netconnection->message, svc_stufftext); MSG_WriteUnterminatedString(&host_client->netconnection->message, "pingplreport"); @@ -696,7 +696,7 @@ static void SV_Pings_f(cmd_state_t *cmd) movementloss = (movementloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS; ping = (int)floor(svs.clients[i].ping*1000+0.5); ping = bound(0, ping, 9999); - if (sv.protocol == PROTOCOL_QUAKEWORLD) + if (sv.protocol == &protocol_quakeworld) { // send qw_svc_updateping and qw_svc_updatepl messages MSG_WriteByte(&host_client->netconnection->message, qw_svc_updateping); @@ -714,7 +714,7 @@ static void SV_Pings_f(cmd_state_t *cmd) MSG_WriteUnterminatedString(&host_client->netconnection->message, temp); } } - if (sv.protocol != PROTOCOL_QUAKEWORLD) + if (sv.protocol != &protocol_quakeworld) MSG_WriteString(&host_client->netconnection->message, "\n"); } @@ -818,7 +818,7 @@ static void SV_Status_f(cmd_state_t *cmd) players++; print ("host: %s\n", Cvar_VariableString (&cvars_all, "hostname", CF_SERVER)); print ("version: %s build %s (gamename %s)\n", gamename, buildstring, gamenetworkfiltername); - print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol)); + print ("protocol: %i (%s)\n", sv.protocol->num, sv.protocol->name); print ("map: %s\n", sv.name); print ("timing: %s\n", Host_TimingReport(vabuf, sizeof(vabuf))); print ("players: %i active (%i max)\n\n", players, svs.maxclients); @@ -885,7 +885,7 @@ static void SV_Status_f(cmd_state_t *cmd) if (in == 0) // default layout { - if (sv.protocol == PROTOCOL_QUAKE && svs.maxclients <= 99) + if (sv.protocol == &protocol_netquake && svs.maxclients <= 99) { // LadyHavoc: this is very touchy because we must maintain ProQuake compatible status output print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", i+1, client->name, frags, hours, minutes, seconds); diff --git a/sv_ents.c b/sv_ents.c index 8e732cd5..34186e9d 100644 --- a/sv_ents.c +++ b/sv_ents.c @@ -84,7 +84,7 @@ void EntityState_WriteExtendBits(sizebuf_t *msg, unsigned int bits) void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned int bits) { - if (sv.protocol == PROTOCOL_DARKPLACES2) + if (sv.protocol == &protocol_dpp2) { if (bits & E_ORIGIN1) MSG_WriteCoord16i(msg, ent->origin[0]); @@ -117,7 +117,7 @@ void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned MSG_WriteCoord32f(msg, ent->origin[2]); } } - if ((sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) && (ent->flags & RENDER_LOWPRECISION)) + if ((sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3 || sv.protocol == &protocol_dpp4) && (ent->flags & RENDER_LOWPRECISION)) { if (bits & E_ANGLE1) MSG_WriteAngle8i(msg, ent->angles[0]); @@ -159,7 +159,7 @@ void EntityState_WriteFields(const entity_state_t *ent, sizebuf_t *msg, unsigned MSG_WriteByte(msg, ent->glowsize); if (bits & E_GLOWCOLOR) MSG_WriteByte(msg, ent->glowcolor); - if (sv.protocol == PROTOCOL_DARKPLACES2) + if (sv.protocol == &protocol_dpp2) if (bits & E_FLAGS) MSG_WriteByte(msg, ent->flags); if (bits & E_TAGATTACHMENT) diff --git a/sv_ents5.c b/sv_ents5.c index 98be9b36..bed601f1 100644 --- a/sv_ents5.c +++ b/sv_ents5.c @@ -516,7 +516,7 @@ qbool EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database packetlog = NULL; // write stat updates - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5) + if (sv.protocol != &protocol_netquake && sv.protocol != &protocol_quakedp && sv.protocol != &protocol_nehahramovie && sv.protocol != &protocol_nehahrabjp && sv.protocol != &protocol_nehahrabjp2 && sv.protocol != &protocol_nehahrabjp3 && sv.protocol != &protocol_dpp1 && sv.protocol != &protocol_dpp2 && sv.protocol != &protocol_dpp3 && sv.protocol != &protocol_dpp4 && sv.protocol != &protocol_dpp5) { for (i = 0;i < MAX_CL_STATS && msg->cursize + 6 + 11 <= maxsize;i++) { @@ -569,7 +569,7 @@ qbool EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database d->latestframenum = framenum; MSG_WriteByte(msg, svc_entities); MSG_WriteLong(msg, framenum); - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6) + if (sv.protocol != &protocol_netquake && sv.protocol != &protocol_quakedp && sv.protocol != &protocol_nehahramovie && sv.protocol != &protocol_dpp1 && sv.protocol != &protocol_dpp2 && sv.protocol != &protocol_dpp3 && sv.protocol != &protocol_dpp4 && sv.protocol != &protocol_dpp5 && sv.protocol != &protocol_dpp6) MSG_WriteLong(msg, movesequence); for (priority = ENTITYFRAME5_PRIORITYLEVELS - 1;priority >= 0 && packetlog->numstates < ENTITYFRAME5_MAXSTATES;priority--) { diff --git a/sv_ents_nq.c b/sv_ents_nq.c index 8db8a623..1d645417 100644 --- a/sv_ents_nq.c +++ b/sv_ents_nq.c @@ -71,7 +71,7 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co if (baseline.modelindex != s->modelindex) { bits |= U_MODEL; - if ((s->modelindex & 0xFF00) && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3) + if ((s->modelindex & 0xFF00) && sv.protocol != &protocol_nehahrabjp && sv.protocol != &protocol_nehahrabjp2 && sv.protocol != &protocol_nehahrabjp3) bits |= U_MODEL2; } if (baseline.alpha != s->alpha) @@ -86,9 +86,9 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co bits |= U_COLORMOD; // if extensions are disabled, clear the relevant update flags - if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_NEHAHRAMOVIE) + if (sv.protocol == &protocol_netquake || sv.protocol == &protocol_nehahramovie) bits &= 0x7FFF; - if (sv.protocol == PROTOCOL_NEHAHRAMOVIE) + if (sv.protocol == &protocol_nehahramovie) if (s->alpha != 255 || s->effects & EF_FULLBRIGHT) bits |= U_EXTEND1; @@ -106,7 +106,7 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co MSG_WriteByte (&buf, bits); if (bits & U_MOREBITS) MSG_WriteByte(&buf, bits>>8); - if (sv.protocol != PROTOCOL_NEHAHRAMOVIE) + if (sv.protocol != &protocol_nehahramovie) { if (bits & U_EXTEND1) MSG_WriteByte(&buf, bits>>16); if (bits & U_EXTEND2) MSG_WriteByte(&buf, bits>>24); @@ -116,7 +116,7 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co if (bits & U_MODEL) { - if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) MSG_WriteShort(&buf, s->modelindex); else MSG_WriteByte(&buf, s->modelindex); @@ -125,12 +125,12 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co if (bits & U_COLORMAP) MSG_WriteByte(&buf, s->colormap); if (bits & U_SKIN) MSG_WriteByte(&buf, s->skin); if (bits & U_EFFECTS) MSG_WriteByte(&buf, s->effects); - if (bits & U_ORIGIN1) MSG_WriteCoord(&buf, s->origin[0], sv.protocol); - if (bits & U_ANGLE1) MSG_WriteAngle(&buf, s->angles[0], sv.protocol); - if (bits & U_ORIGIN2) MSG_WriteCoord(&buf, s->origin[1], sv.protocol); - if (bits & U_ANGLE2) MSG_WriteAngle(&buf, s->angles[1], sv.protocol); - if (bits & U_ORIGIN3) MSG_WriteCoord(&buf, s->origin[2], sv.protocol); - if (bits & U_ANGLE3) MSG_WriteAngle(&buf, s->angles[2], sv.protocol); + if (bits & U_ORIGIN1) sv.protocol->WriteCoord(&buf, s->origin[0]); + if (bits & U_ANGLE1) sv.protocol->WriteAngle(&buf, s->angles[0]); + if (bits & U_ORIGIN2) sv.protocol->WriteCoord(&buf, s->origin[1]); + if (bits & U_ANGLE2) sv.protocol->WriteAngle(&buf, s->angles[1]); + if (bits & U_ORIGIN3) sv.protocol->WriteCoord(&buf, s->origin[2]); + if (bits & U_ANGLE3) sv.protocol->WriteAngle(&buf, s->angles[2]); if (bits & U_ALPHA) MSG_WriteByte(&buf, s->alpha); if (bits & U_SCALE) MSG_WriteByte(&buf, s->scale); if (bits & U_EFFECTS2) MSG_WriteByte(&buf, s->effects >> 8); @@ -141,7 +141,7 @@ qbool EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, co if (bits & U_MODEL2) MSG_WriteByte(&buf, s->modelindex >> 8); // the nasty protocol - if ((bits & U_EXTEND1) && sv.protocol == PROTOCOL_NEHAHRAMOVIE) + if ((bits & U_EXTEND1) && sv.protocol == &protocol_nehahramovie) { if (s->effects & EF_FULLBRIGHT) { diff --git a/sv_main.c b/sv_main.c index 789b7dd0..75b2f1b4 100644 --- a/sv_main.c +++ b/sv_main.c @@ -670,9 +670,7 @@ void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count) if (sv.datagram.cursize > MAX_PACKETFRAGMENT-18) return; MSG_WriteByte (&sv.datagram, svc_particle); - MSG_WriteCoord (&sv.datagram, org[0], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[1], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[2], sv.protocol); + sv.protocol->WriteVector(&sv.datagram, org); for (i=0 ; i<3 ; i++) MSG_WriteChar (&sv.datagram, (int)bound(-128, dir[i]*16, 127)); MSG_WriteByte (&sv.datagram, count); @@ -694,9 +692,7 @@ void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, if (sv.datagram.cursize > MAX_PACKETFRAGMENT-19) return; MSG_WriteByte (&sv.datagram, svc_effect2); - MSG_WriteCoord (&sv.datagram, org[0], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[1], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[2], sv.protocol); + sv.protocol->WriteVector(&sv.datagram, org); MSG_WriteShort (&sv.datagram, modelindex); MSG_WriteShort (&sv.datagram, startframe); MSG_WriteByte (&sv.datagram, framecount); @@ -707,9 +703,7 @@ void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, if (sv.datagram.cursize > MAX_PACKETFRAGMENT-17) return; MSG_WriteByte (&sv.datagram, svc_effect); - MSG_WriteCoord (&sv.datagram, org[0], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[1], sv.protocol); - MSG_WriteCoord (&sv.datagram, org[2], sv.protocol); + sv.protocol->WriteVector(&sv.datagram, org); MSG_WriteByte (&sv.datagram, modelindex); MSG_WriteByte (&sv.datagram, startframe); MSG_WriteByte (&sv.datagram, framecount); @@ -800,12 +794,12 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int n } else MSG_WriteShort (dest, (ent<<3) | channel); - if ((field_mask & SND_LARGESOUND) || sv.protocol == PROTOCOL_NEHAHRABJP2) + if ((field_mask & SND_LARGESOUND) || sv.protocol == &protocol_nehahrabjp2) MSG_WriteShort (dest, sound_num); else MSG_WriteByte (dest, sound_num); for (i = 0;i < 3;i++) - MSG_WriteCoord (dest, PRVM_serveredictvector(entity, origin)[i]+0.5*(PRVM_serveredictvector(entity, mins)[i]+PRVM_serveredictvector(entity, maxs)[i]), sv.protocol); + sv.protocol->WriteCoord (dest, PRVM_serveredictvector(entity, origin)[i]+0.5*(PRVM_serveredictvector(entity, mins)[i]+PRVM_serveredictvector(entity, maxs)[i])); // TODO do we have to do anything here when dest is &sv.reliable_datagram? if(!reliable) @@ -827,7 +821,7 @@ function, therefore the check for it is omitted. */ void SV_StartPointSound (vec3_t origin, const char *sample, int nvolume, float attenuation, float speed) { - int sound_num, field_mask, i, speed4000; + int sound_num, field_mask, speed4000; if (nvolume < 0 || nvolume > 255) { @@ -875,8 +869,7 @@ void SV_StartPointSound (vec3_t origin, const char *sample, int nvolume, float a MSG_WriteShort (&sv.datagram, sound_num); else MSG_WriteByte (&sv.datagram, sound_num); - for (i = 0;i < 3;i++) - MSG_WriteCoord (&sv.datagram, origin[i], sv.protocol); + sv.protocol->WriteVector(&sv.datagram, origin); SV_FlushBroadcastMessages(); } @@ -928,11 +921,11 @@ void SV_SendServerinfo (client_t *client) memset(client->stats, 0, sizeof(client->stats)); memset(client->statsdeltabits, 0, sizeof(client->statsdeltabits)); - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3) + if (sv.protocol != &protocol_netquake && sv.protocol != &protocol_quakedp && sv.protocol != &protocol_nehahramovie && sv.protocol != &protocol_nehahrabjp && sv.protocol != &protocol_nehahrabjp2 && sv.protocol != &protocol_nehahrabjp3) { - if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3) + if (sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3) client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool); - else if (sv.protocol == PROTOCOL_DARKPLACES4) + else if (sv.protocol == &protocol_dpp4) client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_mempool); else client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool); @@ -994,7 +987,7 @@ void SV_SendServerinfo (client_t *client) sb.data = (unsigned char *) buf; sb.maxsize = sizeof(buf); k = 0; - while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, k++, &sb, sv.protocol)) + while(MakeDownloadPacket(sv.csqc_progname, svs.csqc_progdata, sv.csqc_progsize, sv.csqc_progcrc, k++, &sb, sv.protocol->num)) SV_WriteDemoMessage(client, &sb, false); } @@ -1024,7 +1017,7 @@ void SV_SendServerinfo (client_t *client) } MSG_WriteByte (&client->netconnection->message, svc_serverinfo); - MSG_WriteLong (&client->netconnection->message, Protocol_NumberForEnum(sv.protocol)); + MSG_WriteLong (&client->netconnection->message, sv.protocol->num); MSG_WriteByte (&client->netconnection->message, svs.maxclients); if (!coop.integer && deathmatch.integer) @@ -1822,7 +1815,7 @@ static void SV_MarkWriteEntityStateToClient(entity_state_t *s) // always send world submodels in newer protocols because they don't // generate much traffic (in old protocols they hog bandwidth) // but only if sv_cullentities_nevercullbmodels is off - else if (!(s->effects & EF_NODEPTHTEST) && (!isbmodel || !sv_cullentities_nevercullbmodels.integer || sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)) + else if (!(s->effects & EF_NODEPTHTEST) && (!isbmodel || !sv_cullentities_nevercullbmodels.integer || sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie)) { // entity has survived every check so far, check if visible ed = PRVM_EDICT_NUM(s->number); @@ -2150,7 +2143,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t MSG_WriteByte (msg, (int)PRVM_serveredictfloat(ent, dmg_save)); MSG_WriteByte (msg, (int)PRVM_serveredictfloat(ent, dmg_take)); for (i=0 ; i<3 ; i++) - MSG_WriteCoord (msg, PRVM_serveredictvector(other, origin)[i] + 0.5*(PRVM_serveredictvector(other, mins)[i] + PRVM_serveredictvector(other, maxs)[i]), sv.protocol); + sv.protocol->WriteCoord (msg, PRVM_serveredictvector(other, origin)[i] + 0.5*(PRVM_serveredictvector(other, mins)[i] + PRVM_serveredictvector(other, maxs)[i])); PRVM_serveredictfloat(ent, dmg_take) = 0; PRVM_serveredictfloat(ent, dmg_save) = 0; @@ -2177,7 +2170,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t { MSG_WriteByte (msg, svc_setangle); for (i=0 ; i < 3 ; i++) - MSG_WriteAngle (msg, host_client->fixangle_angles[i], sv.protocol); + sv.protocol->WriteAngle (msg, host_client->fixangle_angles[i]); host_client->fixangle_angles_set = false; } @@ -2214,7 +2207,7 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t { if (PRVM_serveredictvector(ent, punchangle)[i]) bits |= (SU_PUNCH1<netconnection)) return; - // PROTOCOL_DARKPLACES5 and later support packet size limiting of updates + // &protocol_dpp5 and later support packet size limiting of updates maxrate = max(NET_MINRATE, sv_maxrate.integer); if (sv_maxrate.integer != maxrate) Cvar_SetValueQuick(&sv_maxrate, maxrate); @@ -2482,10 +2475,9 @@ static void SV_SendClientDatagram (client_t *client) // (how long to wait before sending another, based on this packet's size) clientrate = bound(NET_MINRATE, client->rate, maxrate); - switch (sv.protocol) + switch (sv.protocol->num) { case PROTOCOL_QUAKE: - case PROTOCOL_QUAKEDP: case PROTOCOL_NEHAHRAMOVIE: case PROTOCOL_NEHAHRABJP: case PROTOCOL_NEHAHRABJP2: @@ -2735,7 +2727,7 @@ void SV_SendClientMessages(void) { int i, prepared = false; - if (sv.protocol == PROTOCOL_QUAKEWORLD) + if (sv.protocol == &protocol_quakeworld) Sys_Error("SV_SendClientMessages: no quakeworld support\n"); SV_FlushBroadcastMessages(); @@ -3023,7 +3015,7 @@ SV_ModelIndex */ int SV_ModelIndex(const char *s, int precachemode) { - int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_MODELS); + int i, limit = ((sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) ? 256 : MAX_MODELS); char filename[MAX_QPATH]; if (!s || !*s) return 0; @@ -3037,7 +3029,7 @@ int SV_ModelIndex(const char *s, int precachemode) { if (precachemode) { - if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)) + if (sv.state != ss_loading && (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3 || sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3 || sv.protocol == &protocol_dpp4 || sv.protocol == &protocol_dpp5)) { Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename); return 0; @@ -3086,7 +3078,7 @@ SV_SoundIndex */ int SV_SoundIndex(const char *s, int precachemode) { - int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) ? 256 : MAX_SOUNDS); + int i, limit = ((sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) ? 256 : MAX_SOUNDS); char filename[MAX_QPATH]; if (!s || !*s) return 0; @@ -3100,7 +3092,7 @@ int SV_SoundIndex(const char *s, int precachemode) { if (precachemode) { - if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)) + if (sv.state != ss_loading && (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3 || sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3 || sv.protocol == &protocol_dpp4 || sv.protocol == &protocol_dpp5)) { Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename); return 0; @@ -3278,7 +3270,7 @@ static void SV_CreateBaseline (void) if (svent->priv.server->baseline.modelindex & 0xFF00 || svent->priv.server->baseline.frame & 0xFF00) { large = true; - if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) large = false; } @@ -3294,7 +3286,7 @@ static void SV_CreateBaseline (void) MSG_WriteShort (&sv.signon, svent->priv.server->baseline.modelindex); MSG_WriteShort (&sv.signon, svent->priv.server->baseline.frame); } - else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + else if (sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) { MSG_WriteShort (&sv.signon, svent->priv.server->baseline.modelindex); MSG_WriteByte (&sv.signon, svent->priv.server->baseline.frame); @@ -3308,8 +3300,8 @@ static void SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, svent->priv.server->baseline.skin); for (i=0 ; i<3 ; i++) { - MSG_WriteCoord(&sv.signon, svent->priv.server->baseline.origin[i], sv.protocol); - MSG_WriteAngle(&sv.signon, svent->priv.server->baseline.angles[i], sv.protocol); + sv.protocol->WriteCoord(&sv.signon, svent->priv.server->baseline.origin[i]); + sv.protocol->WriteAngle(&sv.signon, svent->priv.server->baseline.angles[i]); } } } @@ -3533,13 +3525,13 @@ void SV_SpawnServer (const char *map) Cvar_SetQuick(&sv_worldnamenoextension, sv.worldnamenoextension); Cvar_SetQuick(&sv_worldbasename, sv.worldbasename); - sv.protocol = Protocol_EnumForName(sv_protocolname.string); - if (sv.protocol == PROTOCOL_UNKNOWN) + sv.protocol = Protocol_ForName(sv_protocolname.string); + if (!sv.protocol) { char buffer[1024]; Protocol_Names(buffer, sizeof(buffer)); Con_Printf(CON_ERROR "Unknown sv_protocolname \"%s\", valid values are:\n%s\n", sv_protocolname.string, buffer); - sv.protocol = PROTOCOL_QUAKE; + sv.protocol = &protocol_netquake; } // load progs to get entity field count @@ -3660,7 +3652,7 @@ void SV_SpawnServer (const char *map) Mod_PurgeUnused(); // create a baseline for more efficient communications - if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) SV_CreateBaseline (); sv.state = ss_active; // LadyHavoc: workaround for svc_precache bug @@ -3917,13 +3909,13 @@ static void SV_VM_Setup(void) prog->builtins = vm_sv_builtins; prog->numbuiltins = vm_sv_numbuiltins; prog->max_edicts = 512; - if (sv.protocol == PROTOCOL_QUAKE) + if (sv.protocol == &protocol_netquake) prog->limit_edicts = 640; // before quake mission pack 1 this was 512 - else if (sv.protocol == PROTOCOL_QUAKEDP) + else if (sv.protocol == &protocol_quakedp) prog->limit_edicts = 2048; // guessing - else if (sv.protocol == PROTOCOL_NEHAHRAMOVIE) + else if (sv.protocol == &protocol_nehahramovie) prog->limit_edicts = 2048; // guessing! - else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + else if (sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) prog->limit_edicts = 4096; // guessing! else prog->limit_edicts = MAX_EDICTS; diff --git a/sv_protocol.c b/sv_protocol.c new file mode 100644 index 00000000..13cae8ce --- /dev/null +++ b/sv_protocol.c @@ -0,0 +1,66 @@ +#include "quakedef.h" +#include "sv_protocol_base.h" + +protocol_netmsg_t netmsg_base_clc[] = +{ + {"clc_bad", NULL}, + {"clc_nop", Netmsg_clc_nop}, + {"clc_disconnect", Netmsg_clc_disconnect}, + {"clc_move", Netmsg_clc_move}, + {"clc_stringcmd", Netmsg_clc_stringcmd}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {NULL, NULL}, + {"clc_ackframe", Netmsg_clc_ackframe}, + {"clc_ackdownloaddata", Netmsg_clc_ackdownloaddata}, + {"clc_unusedlh2", NULL}, + {"clc_unusedlh3", NULL}, + {"clc_unusedlh4", NULL}, + {"clc_unusedlh5", NULL}, + {"clc_unusedlh6", NULL}, + {"clc_unusedlh7", NULL}, + {"clc_unusedlh8", NULL}, + {"clc_unusedlh9", NULL} +}; \ No newline at end of file diff --git a/sv_protocol_base.h b/sv_protocol_base.h new file mode 100644 index 00000000..e76e02b0 --- /dev/null +++ b/sv_protocol_base.h @@ -0,0 +1,142 @@ +#include "quakedef.h" +#include "server.h" +#include "protocol.h" +#include "sv_user.h" + +static void Netmsg_clc_nop(protocol_t *protocol) +{ +} + +static void Netmsg_clc_stringcmd(protocol_t *protocol) +{ + prvm_prog_t *prog = SVVM_prog; + char *s, *p, *q; + + // allow reliable messages now as the client is done with initial loading + if (host_client->sendsignon == 2) + host_client->sendsignon = 0; + s = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)); + q = NULL; + for(p = s; *p; ++p) switch(*p) + { + case 10: + case 13: + if(!q) + q = p; + break; + default: + if(q) + goto clc_stringcmd_invalid; // newline seen, THEN something else -> possible exploit + break; + } + if(q) + *q = 0; + if (strncasecmp(s, "spawn", 5) == 0 + || strncasecmp(s, "begin", 5) == 0 + || strncasecmp(s, "prespawn", 8) == 0) + Cmd_ExecuteString (&cmd_serverfromclient, s, src_client, true); + else if (PRVM_serverfunction(SV_ParseClientCommand)) + { + int restorevm_tempstringsbuf_cursize; + restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; + PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s); + PRVM_serverglobalfloat(time) = sv.time; + PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict); + prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing"); + prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; + } + else + Cmd_ExecuteString (&cmd_serverfromclient, s, src_client, true); + return; + +clc_stringcmd_invalid: + Con_Printf("Received invalid stringcmd from %s\n", host_client->name); + if(developer.integer > 0) + Com_HexDumpToConsole((unsigned char *) s, (int)strlen(s)); + return; +} + +static void Netmsg_clc_disconnect(protocol_t *protocol) +{ + SV_DropClient (false); // client wants to disconnect +} + +static void Netmsg_clc_move(protocol_t *protocol) +{ + SV_ReadClientMove(); +} + +static void Netmsg_clc_ackdownloaddata(protocol_t *protocol) +{ + int start = MSG_ReadLong(&sv_message); + int num = MSG_ReadShort(&sv_message); + if (host_client->download_file && host_client->download_started) + { + if (host_client->download_expectedposition == start) + { + int size = (int)FS_FileSize(host_client->download_file); + // a data block was successfully received by the client, + // update the expected position on the next data block + host_client->download_expectedposition = start + num; + // if this was the last data block of the file, it's done + if (host_client->download_expectedposition >= FS_FileSize(host_client->download_file)) + { + // tell the client that the download finished + // we need to calculate the crc now + // + // note: at this point the OS probably has the file + // entirely in memory, so this is a faster operation + // now than it was when the download started. + // + // it is also preferable to do this at the end of the + // download rather than the start because it reduces + // potential for Denial Of Service attacks against the + // server. + int crc; + unsigned char *temp; + FS_Seek(host_client->download_file, 0, SEEK_SET); + temp = (unsigned char *) Mem_Alloc(tempmempool, size); + FS_Read(host_client->download_file, temp, size); + crc = CRC_Block(temp, size); + Mem_Free(temp); + // calculated crc, send the file info to the client + // (so that it can verify the data) + SV_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name); + Con_DPrintf("Download of %s by %s has finished\n", host_client->download_name, host_client->name); + FS_Close(host_client->download_file); + host_client->download_file = NULL; + host_client->download_name[0] = 0; + host_client->download_expectedposition = 0; + host_client->download_started = false; + } + } + else + { + // a data block was lost, reset to the expected position + // and resume sending from there + FS_Seek(host_client->download_file, host_client->download_expectedposition, SEEK_SET); + } + } +} + +static void Netmsg_clc_ackframe(protocol_t *protocol) +{ + int num; + if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); + num = MSG_ReadLong(&sv_message); + if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); + if (developer_networkentities.integer >= 10) + Con_Printf("recv clc_ackframe %i\n", num); + // if the client hasn't progressed through signons yet, + // ignore any clc_ackframes we get (they're probably from the + // previous level) + if (host_client->begun && host_client->latestframenum < num) + { + int i; + for (i = host_client->latestframenum + 1;i < num;i++) + if (!SV_FrameLost(i)) + break; + SV_FrameAck(num); + host_client->latestframenum = num; + } +} diff --git a/sv_user.c b/sv_user.c index 7f14e19f..fd6759d7 100644 --- a/sv_user.c +++ b/sv_user.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "sv_demo.h" +#include "sv_user.h" #define DEBUGMOVES 0 static usercmd_t usercmd; @@ -179,16 +180,16 @@ void SV_Spawn_f(cmd_state_t *cmd) if (sv.loadgame) { MSG_WriteByte (&host_client->netconnection->message, svc_setangle); - MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[0], sv.protocol); - MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[1], sv.protocol); - MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol); + sv.protocol->WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[0]); + sv.protocol->WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[1]); + sv.protocol->WriteAngle (&host_client->netconnection->message, 0); } else { MSG_WriteByte (&host_client->netconnection->message, svc_setangle); - MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[0], sv.protocol); - MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[1], sv.protocol); - MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol); + sv.protocol->WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[0]); + sv.protocol->WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[1]); + sv.protocol->WriteAngle (&host_client->netconnection->message, 0); } SV_WriteClientdataToMessage (host_client, host_client->edict, &host_client->netconnection->message, stats); @@ -651,7 +652,7 @@ SV_ReadClientMove */ int sv_numreadmoves = 0; usercmd_t sv_readmoves[CL_MAX_USERCMDS]; -static void SV_ReadClientMove (void) +void SV_ReadClientMove (void) { prvm_prog_t *prog = SVVM_prog; int i; @@ -663,7 +664,7 @@ static void SV_ReadClientMove (void) if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // read ping time - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6) + if (sv.protocol != &protocol_netquake && sv.protocol != &protocol_quakedp && sv.protocol != &protocol_nehahramovie && sv.protocol != &protocol_nehahrabjp && sv.protocol != &protocol_nehahrabjp2 && sv.protocol != &protocol_nehahrabjp3 && sv.protocol != &protocol_dpp1 && sv.protocol != &protocol_dpp2 && sv.protocol != &protocol_dpp3 && sv.protocol != &protocol_dpp4 && sv.protocol != &protocol_dpp5 && sv.protocol != &protocol_dpp6) move->sequence = MSG_ReadLong(&sv_message); move->time = move->clienttime = MSG_ReadFloat(&sv_message); if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); @@ -679,11 +680,11 @@ static void SV_ReadClientMove (void) // read current angles for (i = 0;i < 3;i++) { - if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) move->viewangles[i] = MSG_ReadAngle8i(&sv_message); - else if (sv.protocol == PROTOCOL_DARKPLACES1) + else if (sv.protocol == &protocol_dpp1) move->viewangles[i] = MSG_ReadAngle16i(&sv_message); - else if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3) + else if (sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3) move->viewangles[i] = MSG_ReadAngle32f(&sv_message); else move->viewangles[i] = MSG_ReadAngle16i(&sv_message); @@ -699,7 +700,7 @@ static void SV_ReadClientMove (void) // read buttons // be sure to bitwise OR them into the move->buttons because we want to // accumulate button presses from multiple packets per actual move - if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5) + if (sv.protocol == &protocol_netquake || sv.protocol == &protocol_quakedp || sv.protocol == &protocol_nehahramovie || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3 || sv.protocol == &protocol_dpp1 || sv.protocol == &protocol_dpp2 || sv.protocol == &protocol_dpp3 || sv.protocol == &protocol_dpp4 || sv.protocol == &protocol_dpp5) move->buttons = MSG_ReadByte(&sv_message); else move->buttons = MSG_ReadLong(&sv_message); @@ -710,7 +711,7 @@ static void SV_ReadClientMove (void) if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); // PRYDON_CLIENTCURSOR - if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_NEHAHRABJP && sv.protocol != PROTOCOL_NEHAHRABJP2 && sv.protocol != PROTOCOL_NEHAHRABJP3 && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5) + if (sv.protocol != &protocol_netquake && sv.protocol != &protocol_quakedp && sv.protocol != &protocol_nehahramovie && sv.protocol != &protocol_nehahrabjp && sv.protocol != &protocol_nehahrabjp2 && sv.protocol != &protocol_nehahrabjp3 && sv.protocol != &protocol_dpp1 && sv.protocol != &protocol_dpp2 && sv.protocol != &protocol_dpp3 && sv.protocol != &protocol_dpp4 && sv.protocol != &protocol_dpp5) { // 30 bytes move->cursor_screen[0] = MSG_ReadShort(&sv_message) * (1.0f / 32767.0f); @@ -973,7 +974,7 @@ void SV_ApplyClientMove (void) PRVM_serveredictfloat(host_client->edict, ping_movementloss) = movementloss / (float) NETGRAPH_PACKETS; } -static qbool SV_FrameLost(int framenum) +qbool SV_FrameLost(int framenum) { if (host_client->entitydatabase5) { @@ -987,7 +988,7 @@ static qbool SV_FrameLost(int framenum) return false; } -static void SV_FrameAck(int framenum) +void SV_FrameAck(int framenum) { if (host_client->entitydatabase) EntityFrame_AckFrame(host_client->entitydatabase, framenum); @@ -1004,9 +1005,8 @@ SV_ReadClientMessage */ void SV_ReadClientMessage(void) { - prvm_prog_t *prog = SVVM_prog; - int netcmd, num, start; - char *s, *p, *q; + int netcmd; + protocol_t *protocol = sv.protocol; if(sv_autodemo_perclient.integer >= 2) SV_WriteDemoMessage(host_client, &(host_client->netconnection->message), true); @@ -1014,7 +1014,7 @@ void SV_ReadClientMessage(void) //MSG_BeginReading (); sv_numreadmoves = 0; - for(;;) + while(host_client) { if (!host_client->active) { @@ -1038,143 +1038,16 @@ void SV_ReadClientMessage(void) SV_ExecuteClientMoves(); break; } - - switch (netcmd) + if(!netcmd || netcmd >= protocol->max_clcmsg || !protocol->clcmsg[netcmd].func) { - default: Con_Printf("SV_ReadClientMessage: unknown command char %i (at offset 0x%x)\n", netcmd, sv_message.readcount); if (developer_networking.integer) Com_HexDumpToConsole(sv_message.data, sv_message.cursize); SV_DropClient (false); return; - - case clc_nop: - break; - - case clc_stringcmd: - // allow reliable messages now as the client is done with initial loading - if (host_client->sendsignon == 2) - host_client->sendsignon = 0; - s = MSG_ReadString(&sv_message, sv_readstring, sizeof(sv_readstring)); - q = NULL; - for(p = s; *p; ++p) switch(*p) - { - case 10: - case 13: - if(!q) - q = p; - break; - default: - if(q) - goto clc_stringcmd_invalid; // newline seen, THEN something else -> possible exploit - break; - } - if(q) - *q = 0; - if (strncasecmp(s, "spawn", 5) == 0 - || strncasecmp(s, "begin", 5) == 0 - || strncasecmp(s, "prespawn", 8) == 0) - Cmd_ExecuteString (&cmd_serverfromclient, s, src_client, true); - else if (PRVM_serverfunction(SV_ParseClientCommand)) - { - int restorevm_tempstringsbuf_cursize; - restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; - PRVM_G_INT(OFS_PARM0) = PRVM_SetTempString(prog, s); - PRVM_serverglobalfloat(time) = sv.time; - PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict); - prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ParseClientCommand), "QC function SV_ParseClientCommand is missing"); - prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; - } - else - Cmd_ExecuteString (&cmd_serverfromclient, s, src_client, true); - break; - -clc_stringcmd_invalid: - Con_Printf("Received invalid stringcmd from %s\n", host_client->name); - if(developer.integer > 0) - Com_HexDumpToConsole((unsigned char *) s, (int)strlen(s)); - break; - - case clc_disconnect: - SV_DropClient (false); // client wants to disconnect - return; - - case clc_move: - SV_ReadClientMove(); - break; - - case clc_ackdownloaddata: - start = MSG_ReadLong(&sv_message); - num = MSG_ReadShort(&sv_message); - if (host_client->download_file && host_client->download_started) - { - if (host_client->download_expectedposition == start) - { - int size = (int)FS_FileSize(host_client->download_file); - // a data block was successfully received by the client, - // update the expected position on the next data block - host_client->download_expectedposition = start + num; - // if this was the last data block of the file, it's done - if (host_client->download_expectedposition >= FS_FileSize(host_client->download_file)) - { - // tell the client that the download finished - // we need to calculate the crc now - // - // note: at this point the OS probably has the file - // entirely in memory, so this is a faster operation - // now than it was when the download started. - // - // it is also preferable to do this at the end of the - // download rather than the start because it reduces - // potential for Denial Of Service attacks against the - // server. - int crc; - unsigned char *temp; - FS_Seek(host_client->download_file, 0, SEEK_SET); - temp = (unsigned char *) Mem_Alloc(tempmempool, size); - FS_Read(host_client->download_file, temp, size); - crc = CRC_Block(temp, size); - Mem_Free(temp); - // calculated crc, send the file info to the client - // (so that it can verify the data) - SV_ClientCommands("\ncl_downloadfinished %i %i %s\n", size, crc, host_client->download_name); - Con_DPrintf("Download of %s by %s has finished\n", host_client->download_name, host_client->name); - FS_Close(host_client->download_file); - host_client->download_file = NULL; - host_client->download_name[0] = 0; - host_client->download_expectedposition = 0; - host_client->download_started = false; - } - } - else - { - // a data block was lost, reset to the expected position - // and resume sending from there - FS_Seek(host_client->download_file, host_client->download_expectedposition, SEEK_SET); - } - } - break; - - case clc_ackframe: - if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); - num = MSG_ReadLong(&sv_message); - if (sv_message.badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__); - if (developer_networkentities.integer >= 10) - Con_Printf("recv clc_ackframe %i\n", num); - // if the client hasn't progressed through signons yet, - // ignore any clc_ackframes we get (they're probably from the - // previous level) - if (host_client->begun && host_client->latestframenum < num) - { - int i; - for (i = host_client->latestframenum + 1;i < num;i++) - if (!SV_FrameLost(i)) - break; - SV_FrameAck(num); - host_client->latestframenum = num; - } - break; } + else + protocol->clcmsg[netcmd].func(protocol); } } diff --git a/sv_user.h b/sv_user.h new file mode 100644 index 00000000..d60b0539 --- /dev/null +++ b/sv_user.h @@ -0,0 +1,5 @@ +#include "qtypes.h" + +void SV_ReadClientMove (void); +qbool SV_FrameLost(int framenum); +void SV_FrameAck(int framenum); \ No newline at end of file diff --git a/svvm_cmds.c b/svvm_cmds.c index 634de814..ffb9af8e 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -495,9 +495,9 @@ static void VM_SV_ambientsound(prvm_prog_t *prog) else MSG_WriteByte (&sv.signon, svc_spawnstaticsound); - MSG_WriteVector(&sv.signon, pos, sv.protocol); + sv.protocol->WriteVector(&sv.signon, pos); - if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + if (large || sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) MSG_WriteShort (&sv.signon, soundnum); else MSG_WriteByte (&sv.signon, soundnum); @@ -1451,13 +1451,13 @@ static void VM_SV_WriteLong(prvm_prog_t *prog) static void VM_SV_WriteAngle(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(2, VM_SV_WriteAngle); - MSG_WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); + sv.protocol->WriteAngle (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1)); } static void VM_SV_WriteCoord(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(2, VM_SV_WriteCoord); - MSG_WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); + sv.protocol->WriteCoord (WriteDest(prog), PRVM_G_FLOAT(OFS_PARM1)); } static void VM_SV_WriteString(prvm_prog_t *prog) @@ -1548,7 +1548,7 @@ static void VM_SV_makestatic(prvm_prog_t *prog) MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex)); MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, frame)); } - else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) + else if (sv.protocol == &protocol_nehahrabjp || sv.protocol == &protocol_nehahrabjp2 || sv.protocol == &protocol_nehahrabjp3) { MSG_WriteByte (&sv.signon,svc_spawnstatic); MSG_WriteShort (&sv.signon, (int)PRVM_serveredictfloat(ent, modelindex)); @@ -1565,8 +1565,8 @@ static void VM_SV_makestatic(prvm_prog_t *prog) MSG_WriteByte (&sv.signon, (int)PRVM_serveredictfloat(ent, skin)); for (i=0 ; i<3 ; i++) { - MSG_WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i], sv.protocol); - MSG_WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i], sv.protocol); + sv.protocol->WriteCoord(&sv.signon, PRVM_serveredictvector(ent, origin)[i]); + sv.protocol->WriteAngle(&sv.signon, PRVM_serveredictvector(ent, angles)[i]); } // throw the entity away now @@ -1880,9 +1880,9 @@ static void VM_SV_te_blood(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOOD); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // velocity MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); @@ -1900,15 +1900,15 @@ static void VM_SV_te_bloodshower(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER); // min - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // speed - MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2)); // count MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); SV_FlushBroadcastMessages(); @@ -1920,9 +1920,9 @@ static void VM_SV_te_explosionrgb(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // color MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255)); MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255)); @@ -1938,17 +1938,17 @@ static void VM_SV_te_particlecube(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE); // min - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color @@ -1956,7 +1956,7 @@ static void VM_SV_te_particlecube(prvm_prog_t *prog) // gravity true/false MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0); // randomvel - MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6)); SV_FlushBroadcastMessages(); } @@ -1968,17 +1968,17 @@ static void VM_SV_te_particlerain(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN); // min - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color @@ -1994,17 +1994,17 @@ static void VM_SV_te_particlesnow(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW); // min - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color @@ -2020,9 +2020,9 @@ static void VM_SV_te_spark(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPARK); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // velocity MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); MSG_WriteChar(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); @@ -2038,9 +2038,9 @@ static void VM_SV_te_gunshotquad(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2050,9 +2050,9 @@ static void VM_SV_te_spikequad(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2062,9 +2062,9 @@ static void VM_SV_te_superspikequad(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2074,9 +2074,9 @@ static void VM_SV_te_explosionquad(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2086,9 +2086,9 @@ static void VM_SV_te_smallflash(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SMALLFLASH); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2100,9 +2100,9 @@ static void VM_SV_te_customflash(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // radius MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255)); // lifetime @@ -2120,9 +2120,9 @@ static void VM_SV_te_gunshot(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOT); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2132,9 +2132,9 @@ static void VM_SV_te_spike(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKE); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2144,9 +2144,9 @@ static void VM_SV_te_superspike(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2156,9 +2156,9 @@ static void VM_SV_te_explosion(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2168,9 +2168,9 @@ static void VM_SV_te_tarexplosion(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2180,9 +2180,9 @@ static void VM_SV_te_wizspike(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_WIZSPIKE); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2192,9 +2192,9 @@ static void VM_SV_te_knightspike(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2204,9 +2204,9 @@ static void VM_SV_te_lavasplash(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LAVASPLASH); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2216,9 +2216,9 @@ static void VM_SV_te_teleport(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TELEPORT); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2228,9 +2228,9 @@ static void VM_SV_te_explosion2(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION2); // origin - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // color MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1)); MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); @@ -2245,13 +2245,13 @@ static void VM_SV_te_lightning1(prvm_prog_t *prog) // owner entity MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); SV_FlushBroadcastMessages(); } @@ -2263,13 +2263,13 @@ static void VM_SV_te_lightning2(prvm_prog_t *prog) // owner entity MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); SV_FlushBroadcastMessages(); } @@ -2281,13 +2281,13 @@ static void VM_SV_te_lightning3(prvm_prog_t *prog) // owner entity MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); SV_FlushBroadcastMessages(); } @@ -2299,13 +2299,13 @@ static void VM_SV_te_beam(prvm_prog_t *prog) // owner entity MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2]); SV_FlushBroadcastMessages(); } @@ -2314,9 +2314,9 @@ static void VM_SV_te_plasmaburn(prvm_prog_t *prog) VM_SAFEPARMCOUNT(1, VM_SV_te_plasmaburn); MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PLASMABURN); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); SV_FlushBroadcastMessages(); } @@ -2326,13 +2326,13 @@ static void VM_SV_te_flamejet(prvm_prog_t *prog) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_FLAMEJET); // org - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2]); // vel - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); - MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1]); + sv.protocol->WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2]); // count MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); SV_FlushBroadcastMessages(); @@ -2834,8 +2834,8 @@ static void VM_SV_trailparticles(prvm_prog_t *prog) MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1)); VectorCopy(PRVM_G_VECTOR(OFS_PARM2), start); VectorCopy(PRVM_G_VECTOR(OFS_PARM3), end); - MSG_WriteVector(&sv.datagram, start, sv.protocol); - MSG_WriteVector(&sv.datagram, end, sv.protocol); + sv.protocol->WriteVector(&sv.datagram, start); + sv.protocol->WriteVector(&sv.datagram, end); SV_FlushBroadcastMessages(); } @@ -2858,15 +2858,15 @@ static void VM_SV_pointparticles(prvm_prog_t *prog) // 1+2+12=15 bytes MSG_WriteByte(&sv.datagram, svc_pointparticles1); MSG_WriteShort(&sv.datagram, effectnum); - MSG_WriteVector(&sv.datagram, org, sv.protocol); + sv.protocol->WriteVector(&sv.datagram, org); } else { // 1+2+12+12+2=29 bytes MSG_WriteByte(&sv.datagram, svc_pointparticles); MSG_WriteShort(&sv.datagram, effectnum); - MSG_WriteVector(&sv.datagram, org, sv.protocol); - MSG_WriteVector(&sv.datagram, vel, sv.protocol); + sv.protocol->WriteVector(&sv.datagram, org); + sv.protocol->WriteVector(&sv.datagram, vel); MSG_WriteShort(&sv.datagram, count); } diff --git a/view.c b/view.c index 938ee2da..57c53dd8 100644 --- a/view.c +++ b/view.c @@ -268,7 +268,7 @@ void V_ParseDamage (void) armor = MSG_ReadByte(&cl_message); blood = MSG_ReadByte(&cl_message); - MSG_ReadVector(&cl_message, from, cls.protocol); + cls.protocol->ReadVector(&cl_message, from); // Send the Dmg Globals to CSQC CL_VM_UpdateDmgGlobals(blood, armor, from); @@ -523,7 +523,7 @@ void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewa if (clintermission) { // entity is a fixed camera, just copy the matrix - if (cls.protocol == PROTOCOL_QUAKEWORLD) + if (cls.protocol == &protocol_quakeworld) Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, cl.qw_intermission_origin[0], cl.qw_intermission_origin[1], cl.qw_intermission_origin[2], cl.qw_intermission_angles[0], cl.qw_intermission_angles[1], cl.qw_intermission_angles[2], 1); else {