From 14e7517b164d4d1d7430e5ab59e9c83577e9bda9 Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 4 Aug 2021 21:16:57 +0000 Subject: [PATCH] Support ezquake's kinda flawed float-ent-coords workaround extension. Update PEXT2_VRINPUTS for base angles (for angle nudges when standing on rotating objects). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5998 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 4 +- engine/client/cl_ents.c | 23 ++++++-- engine/client/cl_input.c | 12 ++-- engine/client/cl_parse.c | 58 +++++++++++++++++++ engine/client/client.h | 1 + engine/common/common.c | 12 ++-- engine/common/common.h | 2 +- engine/common/net_chan.c | 8 ++- engine/common/pmove.c | 4 +- engine/common/pmove.h | 2 +- engine/common/protocol.h | 3 +- engine/server/server.h | 9 ++- engine/server/sv_ents.c | 122 +++++++++++++++++++++++++++++---------- engine/server/sv_main.c | 8 ++- engine/server/sv_phys.c | 9 ++- engine/server/sv_send.c | 71 ++++++++++++++++------- engine/server/sv_user.c | 86 ++++++++++++++++----------- 17 files changed, 321 insertions(+), 113 deletions(-) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index a65864b3..066d655d 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1456,7 +1456,7 @@ static int CL_Record_ParticlesStaticsBaselines(sizebuf_t *buf, int seq) if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { MSG_WriteByte(buf, svcfte_spawnstatic2); - SVFTE_EmitBaseline(es, false, buf, cls.fteprotocolextensions2); + SVFTE_EmitBaseline(es, false, buf, cls.fteprotocolextensions2, cls.ezprotocolextensions1); } //else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas else @@ -1516,7 +1516,7 @@ static int CL_Record_ParticlesStaticsBaselines(sizebuf_t *buf, int seq) if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { MSG_WriteByte(buf, svcfte_spawnbaseline2); - SVFTE_EmitBaseline(es, true, buf, cls.fteprotocolextensions2); + SVFTE_EmitBaseline(es, true, buf, cls.fteprotocolextensions2, cls.ezprotocolextensions1); } //else if (cls.fteprotocolextensions & PEXT_SPAWNSTATIC2) //qw deltas else diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 5b01cbc7..0ca36d88 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -621,13 +621,26 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * news->frame = MSG_ReadByte(); } - if (bits & UF_ORIGINXY) + if (cls.ezprotocolextensions1 & EZPEXT1_FLOATENTCOORDS) { - news->origin[0] = MSG_ReadCoord(); - news->origin[1] = MSG_ReadCoord(); + if (bits & UF_ORIGINXY) + { + news->origin[0] = MSG_ReadFloat(); + news->origin[1] = MSG_ReadFloat(); + } + if (bits & UF_ORIGINZ) + news->origin[2] = MSG_ReadFloat(); + } + else + { + if (bits & UF_ORIGINXY) + { + news->origin[0] = MSG_ReadCoord(); + news->origin[1] = MSG_ReadCoord(); + } + if (bits & UF_ORIGINZ) + news->origin[2] = MSG_ReadCoord(); } - if (bits & UF_ORIGINZ) - news->origin[2] = MSG_ReadCoord(); if ((bits & UF_PREDINFO) && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO)) { diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index b99dc78b..07ad1394 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1276,16 +1276,18 @@ static qboolean CLFTE_SendVRCmd (sizebuf_t *buf, unsigned int seats) cl.numackframes = 0; } - from = &nullcmd; for (seat = 0; seat < seats; seat++) + { + from = &nullcmd; for (frame = last-count; frame < last; frame++) { to = &cl.outframes[frame&UPDATE_MASK].cmd[seat]; - MSGFTE_WriteDeltaUsercmd (buf, from, to); + MSGFTE_WriteDeltaUsercmd (buf, cl.playerview[seat].baseangles, from, to); if (to->impulse && (int)(last-frame)>=cl_c2sImpulseBackup.ival) dontdrop = true; from = to; } + } return dontdrop; } @@ -1788,9 +1790,7 @@ void CL_UpdateSeats(void) { if (!cls.netchan.message.cursize && cl.allocated_client_slots > 1 && cls.state == ca_active && cl.splitclients && (cls.fteprotocolextensions & PEXT_SPLITSCREEN) && cl.worldmodel) { - int targ = cl_splitscreen.ival+1; - if (targ > MAX_SPLITS) - targ = MAX_SPLITS; + int targ = bound(1, cl_splitscreen.ival+1, MAX_SPLITS); if (cl.splitclients < targ) { char *ver; @@ -1823,7 +1823,7 @@ void CL_UpdateSeats(void) InfoBuf_SetStarKey(info, "*ver", ver); InfoBuf_ToString(info, infostr, sizeof(infostr), NULL, NULL, NULL, &cls.userinfosync, info); - CL_SendClientCommand(true, "addseat %i %s", cl.splitclients, COM_QuotedString(infostr, buffer, sizeof(buffer), false)); + CL_SendClientCommand(true, "addseat %i %s", cl.splitclients+1, COM_QuotedString(infostr, buffer, sizeof(buffer), false)); } else if (cl.splitclients > targ && targ >= 1) CL_SendClientCommand(true, "addseat %i", targ); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 65ab2d01..c3b96cd6 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -6929,6 +6929,55 @@ static void CL_ParsePortalState(void) } } +static void CL_ParseBaseAngle(int seat) +{ + int i; + short diff[3]; + short newbase[3]; + vec3_t newang; + + inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK]; + qbyte fl = MSG_ReadByte(); //pitch yaw roll lock + for (i=0 ; i<3 ; i++) + { + if (fl & (1u<packet_entities.fixangles[seat] = true; + VectorCopy (newang, inf->packet_entities.fixedangles[seat]); + } + VectorCopy (newang, cl.playerview[seat].viewangles); + } + VectorCopy (newang, cl.playerview[seat].intermissionangles); +} + #define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); #define SHOWNET2(x, y) if(cl_shownet.value>=2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x); /* @@ -7130,6 +7179,9 @@ void CLQW_ParseServerMessage (void) cl.playerview[destsplit].viewentity=MSGCL_ReadEntity(); break; #endif + case svcfte_setanglebase: + CL_ParseBaseAngle(destsplit); + break; case svcfte_setangledelta: for (i=0 ; i<3 ; i++) ang[i] = cl.playerview[destsplit].viewangles[i] + MSG_ReadAngle16 (); @@ -8385,6 +8437,10 @@ void CLNQ_ParseServerMessage (void) CL_SetStatNumeric (destsplit, i, f, f); } break; + + case svcfte_setanglebase: + CL_ParseBaseAngle(destsplit); + break; case svcfte_setangledelta: for (i=0 ; i<3 ; i++) ang[i] = cl.playerview[destsplit].viewangles[i] + MSG_ReadAngle16 (); @@ -8396,6 +8452,8 @@ void CLNQ_ParseServerMessage (void) case svc_setangle: { inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK]; + if (cls.ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) + MSG_ReadByte(); //0=unknown, 1=tele, 2=spawn for (i=0 ; i<3 ; i++) ang[i] = MSG_ReadAngle(); if (!CSQC_Parse_SetAngles(destsplit, ang, false)) diff --git a/engine/client/client.h b/engine/client/client.h index 9be81270..55939742 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -664,6 +664,7 @@ struct playerview_s vec3_t aimangles; //angles actually being sent to the server (different due to in_vraim) vec3_t viewangles; //current angles vec3_t viewanglechange; //angles set by input code this frame + short baseangles[3]; //networked angles are relative to this value vec3_t intermissionangles; //absolute angles for intermission vec3_t gravitydir; diff --git a/engine/common/common.c b/engine/common/common.c index 77f5c8dc..119de158 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1381,11 +1381,12 @@ static void MSG_WriteVR(int i, sizebuf_t *buf, const usercmd_t *from, const use MSG_WriteFloat(buf, cmd->vr[i].velocity[2]); } } -void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const usercmd_t *cmd) +void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const short baseangles[3], const usercmd_t *from, const usercmd_t *cmd) { unsigned int bits = 0; int i; short d; + // // send the movement message // @@ -1440,15 +1441,16 @@ void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const user if (MSG_CompareVR(VRDEV_LEFT, from, cmd)) bits |= UC_VR_LEFT; - //NOTE: WriteUInt64 actually uses some utf-8-like length coding, so its not quite as bloated as it looks. + //NOTE: WriteUInt64 actually uses some length coding, so its not quite as bloated as it looks. MSG_WriteUInt64(buf, bits); + MSG_WriteUInt64(buf, cmd->servertime-from->servertime); for (i = 0; i < 3; i++) { if (bits & (UC_ANGLE1<angles[i]); + MSG_WriteShort(buf, cmd->angles[i]-baseangles[i]); else MSG_WriteChar(buf, cmd->angles[i]-from->angles[i]); } @@ -1539,7 +1541,9 @@ static void MSG_ReadVR(int i, usercmd_t *cmd) void MSGFTE_ReadDeltaUsercmd (const usercmd_t *from, usercmd_t *cmd) { int i; - unsigned int bits = MSG_ReadUInt64(); + unsigned int bits; + + bits = MSG_ReadUInt64(); if (bits & UC_UNSUPPORTED) { diff --git a/engine/common/common.h b/engine/common/common.h index d44922d8..67b55204 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -318,7 +318,7 @@ void MSG_WriteBigCoord (sizebuf_t *sb, float f); void MSG_WriteAngle (sizebuf_t *sb, float f); void MSG_WriteAngle8 (sizebuf_t *sb, float f); void MSG_WriteAngle16 (sizebuf_t *sb, float f); -void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const struct usercmd_s *from, const struct usercmd_s *cmd); +void MSGFTE_WriteDeltaUsercmd (sizebuf_t *buf, const short baseanges[3], const struct usercmd_s *from, const struct usercmd_s *cmd); void MSGQW_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const struct usercmd_s *cmd); void MSGCL_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const struct usercmd_s *cmd); void MSG_WriteDir (sizebuf_t *sb, float *dir); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 24307091..8bfd781d 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -243,7 +243,13 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq) } else if (protover == PROTOCOL_VERSION_EZQUAKE1) { - mask = EZPEXT1_FLOATENTCOORDS|EZPEXT1_SETANGLEREASON; + mask = EZPEXT1_FLOATENTCOORDS;//|EZPEXT1_SETANGLEREASON; + + if (fornq) + { + mask &= ~EZPEXT1_FLOATENTCOORDS; //keep things simple. interactions are not defined. + mask &= ~EZPEXT1_SETANGLEREASON; //potentially breaks too many nq mods. don't encourage it. + } } return mask; diff --git a/engine/common/pmove.c b/engine/common/pmove.c index 602e4721..be2ebbb6 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -1242,14 +1242,14 @@ static void PM_NudgePosition (void) { for (i=0 ; i<3 ; i++) { - if (pmove.velocity[i]) + /*if (pmove.velocity[i]) { //round in the direction of velocity, which means we're less likely to get stuck. if (pmove.velocity[i] >= 0) nudged[i] = (qintptr_t)(base[i]*8+0.5f) / 8.0; else nudged[i] = (qintptr_t)(base[i]*8-0.5f) / 8.0; } - else + else*/ { if (base[i] >= 0) nudged[i] = (qintptr_t)(base[i]*8+0.5f) / 8.0; diff --git a/engine/common/pmove.h b/engine/common/pmove.h index a9bf8777..a0975437 100644 --- a/engine/common/pmove.h +++ b/engine/common/pmove.h @@ -123,7 +123,7 @@ typedef struct { qboolean autobunny; int stepheight; - qbyte coordtype; //FIXME: EZPEXT1_FLOATENTCOORDS should mean 4, but the result does not match ezquake/mvdsv which would result in inconsistencies. so player coords are rounded inconsistently. + qbyte coordtype; //FIXME: EZPEXT1_FLOATENTCOORDS should mean 4, but the result does not match ezquake/mvdsv's round-towards-origin which would result in inconsistencies. so player coords are rounded inconsistently. unsigned int flags; } movevars_t; diff --git a/engine/common/protocol.h b/engine/common/protocol.h index c8dee7b3..6facd4fb 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -89,7 +89,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences) #define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding... #define EZPEXT1_SETANGLEREASON 0x00000002 //specifies the reason for an svc_setangles call. the mvdsv implementation will fuck over any mods that writebyte them. we'd need to modify our preparse stuff to work around the issue. -#define EZPEXT1_SERVERADVERTISE 0 +#define EZPEXT1_SERVERADVERTISE EZPEXT1_FLOATENTCOORDS/* - implemented, but interactions with replacementdeltas is not defined*/ /*EZPEXT1_SETANGLEREASON - potentially causes compat issues with mods that stuffcmd it (common in nq)*/ #define EZPEXT1_CLIENTADVERTISE EZPEXT1_FLOATENTCOORDS //might as well ask for it, as a way around mvdsv's writecoord/PM_NudgePosition rounding difference bug. #define EZPEXT1_CLIENTSUPPORT (EZPEXT1_FLOATENTCOORDS|EZPEXT1_SETANGLEREASON) //ones we can support in demos. warning if other bits. @@ -330,6 +330,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_cgamepacket_sized 90 //svcfte_cgamepacket with an extra short size right after the svc. #define svcfte_temp_entity_sized 91 //svc_temp_entity with an extra short size right after the svc (high bit means nq, unset means qw). #define svcfte_csqcentities_sized 92 //entity lump for csqc (with size info) +#define svcfte_setanglebase 93 //updates the base angle (and optionally locks the view, otherwise nudging it without race conditions.) //fitz svcs #define svcfitz_skybox 37 diff --git a/engine/server/server.h b/engine/server/server.h index abca7674..59700976 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -360,6 +360,9 @@ typedef struct unsigned short resendstats[32];//the number of each entity that was sent in this frame unsigned int numresendstats; //the bits of each entity that were sent in this frame + short baseangles[MAX_SPLITS][3]; + unsigned int baseanglelocked[MAX_SPLITS]; + //antilag //these are to recalculate the player's origin without old knockbacks nor teleporters, to give more accurate weapon start positions (post-command). vec3_t pmorigin; @@ -502,6 +505,8 @@ typedef struct client_s infosync_t infosync; // information about the infos that the client still doesn't know (server and multiple clients). char *transfer; + unsigned int baseanglelock; // lock the player angles to base (until baseangle sequence is acked) + short baseangles[3]; // incoming angle inputs are relative to this value. usercmd_t lastcmd; // for filling in big drops and partial predictions double localtime; // of last message qboolean jump_held; @@ -1197,7 +1202,7 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info); int SV_ModelIndex (const char *name); void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg); -void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext); +void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext, unsigned int ezext); client_t *SV_AddSplit(client_t *controller, char *info, int id); void SV_SpawnParmsToQC(client_t *client); @@ -1412,7 +1417,7 @@ qboolean PR_ShouldTogglePause(client_t *initiator, qboolean pausedornot); // sv_ents.c // void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignorepvs); -void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg, unsigned int pext2); +void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg, unsigned int pext2, unsigned int ezext); void SVQ3Q1_BuildEntityPacket(client_t *client, packet_entities_t *pack); void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *client, packet_entities_t *pack); int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index b4e198d9..eba8f0df 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -649,7 +649,7 @@ Writes part of a packetentities message. Can delta from either a baseline or a previous packet_entity ================== */ -void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext) +void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean force, unsigned int protext, unsigned int ezext) { #ifdef PROTOCOLEXTENSIONS int evenmorebits=0; @@ -659,19 +659,23 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, int fromeffects; coorddata coordd[3]; coorddata angled[3]; + qbyte coordtype = msg->prim.coordtype; if (from == &((edict_t*)NULL)->baseline) from = &nullentitystate; + if (ezext&EZPEXT1_FLOATENTCOORDS) + coordtype = COORDTYPE_FLOAT_32; + // send an update bits = 0; - if (msg->prim.coordtype != COORDTYPE_FLOAT_32) + if (coordtype != COORDTYPE_FLOAT_32) { for (i=0 ; i<3 ; i++) { - coordd[i] = MSG_ToCoord(to->origin[i], msg->prim.coordtype); - if (MSG_ToCoord(from->origin[i], msg->prim.coordtype).b4 != coordd[i].b4) + coordd[i] = MSG_ToCoord(to->origin[i], coordtype); + if (MSG_ToCoord(from->origin[i], coordtype).b4 != coordd[i].b4) bits |= U_ORIGIN1<origin[i] = from->origin[i]; @@ -681,7 +685,7 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, { for (i=0 ; i<3 ; i++) { - coordd[i] = MSG_ToCoord(to->origin[i], msg->prim.coordtype); + coordd[i] = MSG_ToCoord(to->origin[i], coordtype); if (to->origin[i] != from->origin[i]) bits |= U_ORIGIN1<effects&0x00ff); if (bits & U_ORIGIN1) - SZ_Write(msg, &coordd[0], msg->prim.coordtype&0xf); + SZ_Write(msg, &coordd[0], (coordtype&0xf)); if (bits & U_ANGLE1) SZ_Write(msg, &angled[0], msg->prim.anglesize); if (bits & U_ORIGIN2) - SZ_Write(msg, &coordd[1], msg->prim.coordtype&0xf); + SZ_Write(msg, &coordd[1], (coordtype&0xf)); if (bits & U_ANGLE2) SZ_Write(msg, &angled[1], msg->prim.anglesize); if (bits & U_ORIGIN3) - SZ_Write(msg, &coordd[2], msg->prim.coordtype&0xf); + SZ_Write(msg, &coordd[2], (coordtype&0xf)); if (bits & U_ANGLE3) SZ_Write(msg, &angled[2], msg->prim.anglesize); @@ -1030,7 +1034,7 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, qbyte *frombonedat return bits; } -static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_t *msg, unsigned int pext2, qbyte *boneptr) +static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_t *msg, unsigned int pext2, unsigned int ezext1, qbyte *boneptr) { unsigned int predbits = 0; if (bits & UF_MOVETYPE) @@ -1102,13 +1106,27 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ else MSG_WriteByte(msg, state->frame); } - if (bits & UF_ORIGINXY) + + if (ezext1 & EZPEXT1_FLOATENTCOORDS) { - MSG_WriteCoord(msg, state->origin[0]); - MSG_WriteCoord(msg, state->origin[1]); + if (bits & UF_ORIGINXY) + { + MSG_WriteFloat(msg, state->origin[0]); + MSG_WriteFloat(msg, state->origin[1]); + } + if (bits & UF_ORIGINZ) + MSG_WriteFloat(msg, state->origin[2]); + } + else + { + if (bits & UF_ORIGINXY) + { + MSG_WriteCoord(msg, state->origin[0]); + MSG_WriteCoord(msg, state->origin[1]); + } + if (bits & UF_ORIGINZ) + MSG_WriteCoord(msg, state->origin[2]); } - if (bits & UF_ORIGINZ) - MSG_WriteCoord(msg, state->origin[2]); if ((bits & UF_PREDINFO) && !(pext2 & PEXT2_PREDINFO)) { /*if we have pred info, use more precise angles*/ @@ -1327,13 +1345,13 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ } /*dump out the delta from baseline (used for baselines and statics, so has no svc)*/ -void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg, unsigned int pext2) +void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_t *msg, unsigned int pext2, unsigned int ezext) { unsigned int bits; if (numberisimportant) MSG_WriteEntity(msg, to->number); bits = UF_RESET | SVFTE_DeltaCalcBits(&nullentitystate, NULL, to, NULL); - SVFTE_WriteUpdate(bits, to, msg, pext2, NULL); + SVFTE_WriteUpdate(bits, to, msg, pext2, ezext, NULL); } /*SVFTE_EmitPacketEntities @@ -1508,6 +1526,43 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb outno = 0; outmax = frame->maxresend; + + if (client->fteprotocolextensions2 & PEXT2_VRINPUTS) + { + client_frame_t *ackedframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK]; + client_t *seat; + + for (i = 0, seat = client; i < MAX_SPLITS && seat; i++, seat = seat->controlled) + { + if (ackedframe->baseanglelocked[i] != seat->baseanglelock || + ackedframe->baseangles[i][0] != seat->baseangles[0] || + ackedframe->baseangles[i][1] != seat->baseangles[1] || + ackedframe->baseangles[i][2] != seat->baseangles[2]) + { //change the base angle, and force the client to it. + //sent every frame its valid for, because we really don't want packetloss here. + int fl = 0, j; + for (j = 0; j < 3; j++) + if (seat->baseangles[j]) + fl |= (1u<baseanglelocked[i] != seat->baseanglelock) + fl |= 8; + + if (seat->seat) + { + MSG_WriteByte (msg, svcfte_choosesplitclient); + MSG_WriteByte (msg, seat->seat); + } + MSG_WriteByte (msg, svcfte_setanglebase); + MSG_WriteByte(msg, fl); + for (j = 0; j < 3; j++) + if (fl&(1u<baseangles[j]); + } + VectorCopy(seat->baseangles, frame->baseangles[i]); + frame->baseanglelocked[i] = seat->baseanglelock; + } + } + if (msg->cursize + 52 <= msg->maxsize) { /*start writing the packet*/ @@ -1579,7 +1634,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb resend[outno].bits = bits; SV_EmitDeltaEntIndex(msg, j, false, true); - SVFTE_WriteUpdate(bits, &client->sentents.entities[j], msg, client->fteprotocolextensions2, client->sentents.bonedata); + SVFTE_WriteUpdate(bits, &client->sentents.entities[j], msg, client->fteprotocolextensions2, client->ezprotocolextensions1, client->sentents.bonedata); } client->pendingdeltabits[j] = 0; @@ -1675,7 +1730,7 @@ void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t { // delta update from old position //Con_Printf ("delta %i\n", newnum); #ifdef PROTOCOLEXTENSIONS - SVQW_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, client->fteprotocolextensions); + SVQW_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false, client->fteprotocolextensions, client->ezprotocolextensions1); #else SVQW_WriteDelta (&from->entities[oldindex], &to->entities[newindex], msg, false); #endif @@ -1692,7 +1747,7 @@ void SVQW_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t ent = NULL; //Con_Printf ("baseline %i\n", newnum); #ifdef PROTOCOLEXTENSIONS - SVQW_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true, client->fteprotocolextensions); + SVQW_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true, client->fteprotocolextensions, client->ezprotocolextensions1); #else SVQW_WriteDelta (&ent->baseline, &to->entities[newindex], msg, true); #endif @@ -2127,8 +2182,9 @@ typedef struct { qboolean isself; qboolean onground; qboolean solid; - int fteext; - int zext; + unsigned int fteext1; + unsigned int ezext1; + unsigned int zext; int hull; client_t *cl; } clstate_t; @@ -2188,29 +2244,29 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) if (ent->spectator == 2 && ent->weaponframe) //it's not us, but we are spectating, so we need the correct weaponframe pflags |= PF_WEAPONFRAME; - if (!ent->isself || (ent->fteext & PEXT_SPLITSCREEN)) + if (!ent->isself || (ent->fteext1 & PEXT_SPLITSCREEN)) { #ifdef PEXT_SCALE //this is graphics, not physics - if (ent->fteext & PEXT_SCALE) + if (ent->fteext1 & PEXT_SCALE) { if (ent->scale && ent->scale != 1) pflags |= PF_SCALE; } #endif #ifdef PEXT_TRANS - if (ent->fteext & PEXT_TRANS) + if (ent->fteext1 & PEXT_TRANS) { if (ent->transparency) pflags |= PF_TRANS; } #endif #ifdef PEXT_FATNESS - if (ent->fteext & PEXT_FATNESS) + if (ent->fteext1 & PEXT_FATNESS) { if (ent->fatness) pflags |= PF_FATNESS; } #endif } #ifdef PEXT_HULLSIZE - if (ent->fteext & PEXT_HULLSIZE) + if (ent->fteext1 & PEXT_HULLSIZE) { hullnumber = SV_HullNumForPlayer(ent->hull, ent->mins, ent->maxs); if (hullnumber != 1) @@ -2273,7 +2329,7 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) MSG_WriteByte (msg, svc_playerinfo); MSG_WriteByte (msg, ent->playernum); - if (ent->fteext & (PEXT_HULLSIZE|PEXT_TRANS|PEXT_SCALE|PEXT_FATNESS)) + if (ent->fteext1 & (PEXT_HULLSIZE|PEXT_TRANS|PEXT_SCALE|PEXT_FATNESS)) { if (pflags & 0xff0000) pflags |= PF_EXTRA_PFS; @@ -2286,7 +2342,12 @@ void SV_WritePlayerToClient(sizebuf_t *msg, clstate_t *ent) //we need to tell the client that it's moved, as it's own origin might not be natural for (i=0 ; i<3 ; i++) - MSG_WriteCoord (msg, ent->origin[i]); + { + if (ent->ezext1 & EZPEXT1_FLOATENTCOORDS) + MSG_WriteFloat (msg, ent->origin[i]); + else + MSG_WriteCoord (msg, ent->origin[i]); + } MSG_WriteByte (msg, ent->frame); @@ -2803,7 +2864,8 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * clst.localtime = cl->localtime; clst.health = ent->v->health; clst.spectator = 0; - clst.fteext = client->fteprotocolextensions; + clst.fteext1 = client->fteprotocolextensions; + clst.ezext1 = client->ezprotocolextensions1; clst.zext = client->zquake_extensions; clst.cl = cl; @@ -4227,7 +4289,7 @@ void SV_CleanupEnts(void) //FIXME: check if Version exists and do it earlier. if ((int)ent->xv->Version != sv.csqcentversion[ent->entnum]) { - ent->xv->SendFlags = SENDFLAGS_USABLE; + ent->xv->SendFlags = -1; sv.csqcentversion[ent->entnum] = (int)ent->xv->Version; } #endif diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 1ef4ede8..1b5421b6 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1623,7 +1623,7 @@ qboolean SVC_GetChallenge (qboolean respond_dp) over+=sizeof(lng); } //tell the client what mvdsv/ezquake extensions we support - mask = Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, false); + mask = Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, false)&EZPEXT1_SERVERADVERTISE; if (mask) { lng = LittleLong(PROTOCOL_VERSION_EZQUAKE1); @@ -2002,6 +2002,10 @@ void SV_ClientProtocolExtensionsChanged(client_t *client) client->ezprotocolextensions1 &= Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, ISNQCLIENT(client)) & EZPEXT1_SERVERADVERTISE; client->zquake_extensions &= SERVER_SUPPORTED_Z_EXTENSIONS; + //older versions of fte didn't understand any interactions between ez's limited float support and replacement deltas. so only activate both when vrinputs is also supported. + if ((client->ezprotocolextensions1 & EZPEXT1_FLOATENTCOORDS) && (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) && !(client->fteprotocolextensions2 & PEXT2_VRINPUTS)) + client->ezprotocolextensions1 &= ~EZPEXT1_FLOATENTCOORDS; + //some gamecode can't cope with some extensions for some reasons... and I'm too lazy to fix the code to cope. if (svs.gametype == GT_HALFLIFE) client->fteprotocolextensions2 &= ~PEXT2_REPLACEMENTDELTAS; //baseline issues @@ -2357,9 +2361,11 @@ client_t *SV_AddSplit(client_t *controller, char *info, int id) cl->spectator = asspec; cl->netchan.remote_address = controller->netchan.remote_address; cl->netchan.message.prim = controller->netchan.message.prim; + cl->netchan.netprim = controller->netchan.netprim; cl->zquake_extensions = controller->zquake_extensions; cl->fteprotocolextensions = controller->fteprotocolextensions; cl->fteprotocolextensions2 = controller->fteprotocolextensions2; + cl->ezprotocolextensions1 = controller->ezprotocolextensions1; cl->penalties = controller->penalties; cl->protocol = controller->protocol; cl->maxmodels = controller->maxmodels; diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 3b4c8b0a..e8f55d2e 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -670,7 +670,6 @@ typedef struct wedict_t *ent; vec3_t origin; vec3_t angles; -// float deltayaw; } pushed_t; static pushed_t pushed[1024], *pushed_p; @@ -690,6 +689,9 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec //float oldsolid; pushed_t *p; vec3_t org, org2, move2, forward, right, up; + short yawchange; + + yawchange = (amove[PITCH]||amove[ROLL])?0:ANGLE2SHORT(amove[YAW]); pushed_p = pushed; @@ -768,6 +770,8 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec // try moving the contacted entity VectorAdd (check->v->origin, move, check->v->origin); VectorAdd (check->v->angles, amove, check->v->angles); + if (check->entnum>0&&(check->entnum)<=sv.allocated_client_slots) + svs.clients[check->entnum-1].baseangles[YAW] += yawchange; // figure movement due to the pusher's amove VectorSubtract (check->v->origin, pusher->v->origin, org); @@ -868,6 +872,9 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec VectorCopy (p->origin, p->ent->v->origin); VectorCopy (p->angles, p->ent->v->angles); World_LinkEdict (w, p->ent, false); + + if (p->ent->entnum>0&&(p->ent->entnum)<=sv.allocated_client_slots) + svs.clients[p->ent->entnum-1].baseangles[YAW] -= yawchange; } return false; } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 078659db..c40e84d0 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1644,36 +1644,63 @@ void SV_SendFixAngle(client_t *client, sizebuf_t *msg, int fixtype, qboolean rol else fixtype = FIXANGLE_FIXED; } - if (fixtype == FIXANGLE_DELTA && !(controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) - fixtype = FIXANGLE_FIXED; //sorry, can't do it. + else + roll = true; - if (client->lockanglesseq>=controller->netchan.incoming_acknowledged && controller->netchan.message.cursize < controller->netchan.message.maxsize/2) - msg = NULL; //try to keep them vaugely reliable, where feasable. - if (!msg) - msg = ClientReliable_StartWrite(client, 10); - else if (client->seat) + if (controller->fteprotocolextensions2 & PEXT2_VRINPUTS) { - MSG_WriteByte(msg, svcfte_choosesplitclient); - MSG_WriteByte(msg, client->seat); - } - if (fixtype == FIXANGLE_DELTA && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) - { - MSG_WriteByte (msg, svcfte_setangledelta); - for (i=0 ; i < 3 ; i++) + if (fixtype == FIXANGLE_DELTA) { - int newa = ang[i] - SHORT2ANGLE(client->lastcmd.angles[i]); - MSG_WriteAngle16 (msg, newa); - client->lastcmd.angles[i] = ANGLE2SHORT(ang[i]); + //fiddle with the base angle, server will see future moves with that change already applied. + vec3_t diff; + for (i = 0; i < 3; i++) + diff[i] = ANGLE2SHORT(ang[i]) - client->lastcmd.angles[i]; + if (!roll) + diff[2] = 0; + VectorAdd(client->baseangles, diff, client->baseangles); + } + else + { + client->baseangles[0] = ANGLE2SHORT(ang[0]); + client->baseangles[1] = ANGLE2SHORT(ang[1]); + client->baseangles[2] = ANGLE2SHORT(ang[2]); + client->baseanglelock++; } } else { - MSG_WriteByte (msg, svc_setangle); - if (client->ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) - MSG_WriteByte (msg, (fixtype == FIXANGLE_DELTA)?2:0); //shitty backwards incompatible protocol extension that breaks from writebytes. - for (i=0 ; i < 3 ; i++) - MSG_WriteAngle (msg, (i==2&&!roll)?0:ang[i]); + if (fixtype == FIXANGLE_DELTA && !(controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) + fixtype = FIXANGLE_FIXED; //sorry, can't do it. + + if (client->lockanglesseq>=controller->netchan.incoming_acknowledged && controller->netchan.message.cursize < controller->netchan.message.maxsize/2) + msg = NULL; //try to keep them vaugely reliable, where feasable. + if (!msg) + msg = ClientReliable_StartWrite(client, 10); + else if (client->seat) + { + MSG_WriteByte(msg, svcfte_choosesplitclient); + MSG_WriteByte(msg, client->seat); + } + if (fixtype == FIXANGLE_DELTA && (controller->fteprotocolextensions2 & PEXT2_SETANGLEDELTA)) + { + MSG_WriteByte (msg, svcfte_setangledelta); + for (i=0 ; i < 3 ; i++) + { + int newa = ang[i] - SHORT2ANGLE(client->lastcmd.angles[i]); + MSG_WriteAngle16 (msg, newa); + client->lastcmd.angles[i] = ANGLE2SHORT(ang[i]); + } + } + else + { + MSG_WriteByte (msg, svc_setangle); + if (client->ezprotocolextensions1 & EZPEXT1_SETANGLEREASON) + MSG_WriteByte (msg, (fixtype == FIXANGLE_DELTA)?2:0); //shitty backwards incompatible protocol extension that breaks from writebytes. + for (i=0 ; i < 3 ; i++) + MSG_WriteAngle (msg, (i==2&&!roll)?0:ang[i]); + } } + ClientReliable_FinishWrite(client); client->lockanglesseq = controller->netchan.outgoing_sequence+1; //so that spammed fixangles use absolute values, locking the camera in place. } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 16a894d3..73f8d21b 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -245,7 +245,7 @@ void SV_New_f (void) int playernum; int splitnum; client_t *split; - unsigned int fteext1, fteext2; //reported to client + unsigned int fteext1, fteext2, ezext1; //reported to client host_client->prespawn_stage = PRESPAWN_INVALID; host_client->prespawn_idx = 0; @@ -305,16 +305,19 @@ void SV_New_f (void) fteext1 = host_client->fteprotocolextensions; fteext2 = host_client->fteprotocolextensions2; + ezext1 = host_client->ezprotocolextensions1; switch(svs.netprim.coordtype) { case COORDTYPE_FLOAT_32: fteext1 |= PEXT_FLOATCOORDS; + ezext1 &= ~EZPEXT1_FLOATENTCOORDS; //redundant. if (!(host_client->fteprotocolextensions & PEXT_FLOATCOORDS)) { - SV_ClientPrintf(host_client, 2, "\n\n\n\nPlease set cl_nopext to 0 and then reconnect.\nIf that doesn't work, please update your engine\n"); - Con_Printf("%s does not support bigcoords\n", host_client->name); - host_client->drop = true; - return; + SV_ClientPrintf(host_client, 2, "\nForcing bigcoords.\nIf this doesn't work, please update your engine\n"); + host_client->fteprotocolextensions |= PEXT_FLOATCOORDS; +// Con_Printf("%s does not support bigcoords\n", host_client->name); +// host_client->drop = true; +// return; } break; case COORDTYPE_FIXED_13_3: @@ -342,6 +345,11 @@ void SV_New_f (void) ClientReliableWrite_Long (host_client, PROTOCOL_VERSION_FTE2); ClientReliableWrite_Long (host_client, fteext2); } + if (ezext1)//let the client know + { + ClientReliableWrite_Long (host_client, PROTOCOL_VERSION_EZQUAKE1); + ClientReliableWrite_Long (host_client, ezext1); + } ClientReliableWrite_Long (host_client, ISQ2CLIENT(host_client)?PROTOCOL_VERSION_Q2:PROTOCOL_VERSION_QW); ClientReliableWrite_Long (host_client, svs.spawncount); if (ISQ2CLIENT(host_client)) @@ -1577,7 +1585,7 @@ void SV_SendClientPrespawnInfo(client_t *client) if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { MSG_WriteByte(&client->netchan.message, svcfte_spawnstatic2); - SVFTE_EmitBaseline(state, false, &client->netchan.message, client->fteprotocolextensions2); + SVFTE_EmitBaseline(state, false, &client->netchan.message, client->fteprotocolextensions2, client->ezprotocolextensions1); continue; } if (client->fteprotocolextensions & PEXT_SPAWNSTATIC2) @@ -1586,7 +1594,7 @@ void SV_SendClientPrespawnInfo(client_t *client) if (state->hexen2flags || state->trans || state->modelindex >= 256 || state->frame > 255 || state->scale || state->abslight) { MSG_WriteByte(&client->netchan.message, svcfte_spawnstatic2); - SVQW_WriteDelta(&nullentitystate, state, &client->netchan.message, true, client->fteprotocolextensions); + SVQW_WriteDelta(&nullentitystate, state, &client->netchan.message, true, client->fteprotocolextensions, client->ezprotocolextensions1); continue; } } @@ -1705,12 +1713,12 @@ void SV_SendClientPrespawnInfo(client_t *client) else if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { MSG_WriteByte(&client->netchan.message, svcfte_spawnbaseline2); - SVFTE_EmitBaseline(state, true, &client->netchan.message, client->fteprotocolextensions2); + SVFTE_EmitBaseline(state, true, &client->netchan.message, client->fteprotocolextensions2, client->ezprotocolextensions1); } else if (client->fteprotocolextensions & PEXT_SPAWNSTATIC2) { MSG_WriteByte(&client->netchan.message, svcfte_spawnbaseline2); - SVQW_WriteDelta(&nullentitystate, state, &client->netchan.message, true, client->fteprotocolextensions); + SVQW_WriteDelta(&nullentitystate, state, &client->netchan.message, true, client->fteprotocolextensions, client->ezprotocolextensions1); } else if (ISDPCLIENT(client) && (state->modelindex > 255 || state->frame > 255)) { @@ -5373,14 +5381,14 @@ static void Cmd_AddSeat_f(void) int num = atoi(Cmd_Argv(1)); int count; - if (!num || host_client->joinobservelockeduntil > realtime) + if (num<=0 || host_client->joinobservelockeduntil > realtime) return; if (host_client->netchan.remote_address.type != NA_LOOPBACK) host_client->joinobservelockeduntil = realtime + 2; for (count = 1, prev = host_client, cl = host_client->controlled; cl; cl = cl->controlled) { - if (count > num) + if (count >= num) { for(; cl; cl = prev->controlled) { @@ -5404,8 +5412,8 @@ static void Cmd_AddSeat_f(void) count++; } - if (!changed && count <= num) - changed = !!SV_AddSplit(host_client, Cmd_Argv(2), num); + if (!changed && count+1 == num && Cmd_Argc()>2) + changed = !!SV_AddSplit(host_client, Cmd_Argv(2), num-1); } else { @@ -7939,7 +7947,7 @@ static double SVFTE_ExecuteClientMove(client_t *controller) for (seat = 0; seat < seats; seat++) { if (!split) - { //err, they sent too many seats... assume we kicked one. + { //err, they sent too many seats... assume we kicked one. swallow the extra data. for (frame = 0; frame < frames; frame++) MSGFTE_ReadDeltaUsercmd(&nullcmd, &old); continue; @@ -7960,6 +7968,9 @@ static double SVFTE_ExecuteClientMove(client_t *controller) { MSGFTE_ReadDeltaUsercmd(&old, &split->lastcmd); old = split->lastcmd; + split->lastcmd.angles[0] += split->baseangles[0]; + split->lastcmd.angles[1] += split->baseangles[1]; + split->lastcmd.angles[2] += split->baseangles[2]; if (split->penalties & BAN_CRIPPLED) { @@ -7970,8 +7981,10 @@ static double SVFTE_ExecuteClientMove(client_t *controller) if (split->state == cs_spawned) { + //handle impulse here, doing it later might mean it got skipped entirely (nq physics often skips frames). if (split->lastcmd.impulse) split->edict->v->impulse = split->lastcmd.impulse; + if (split->isindependant) { //this protocol uses bigger timestamps instead of msecs unsigned int curtime = sv.time*1000; @@ -8053,14 +8066,14 @@ void SV_ExecuteClientMessage (client_t *cl) // calc ping time frame = &cl->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; - if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged) + if (cl->lastsequence_acknowledged + UPDATE_BACKUP > cl->netchan.incoming_acknowledged && cl->netchan.incoming_sequence-cl->netchan.incoming_acknowledgedping_time == -1 || !sv_ping_ignorepl.ival) frame->ping_time = realtime - frame->senttime; //no more phenomanally low pings please - if (cl->spectator) + if (cl->spectator || sv_minping.value<=0) cl->delay = 0; else { @@ -8070,7 +8083,7 @@ void SV_ExecuteClientMessage (client_t *cl) //FIXME: we should use actual arrival times instead, so we don't get so much noise and seesawing. diff = bound(-25, diff, 25); //don't swing wildly cl->delay -= 0.001*(diff/25); //scale towards the ideal value - cl->delay = bound(0, cl->delay, 1); //but make sure things don't go crazy + cl->delay = bound(0, cl->delay, UPDATE_BACKUP/77.0); //but make sure things don't go crazy } } if (cl->penalties & BAN_LAGGED) @@ -8455,13 +8468,8 @@ void SVQ2_ExecuteClientMessage (client_t *cl) if (c == -1) break; - switch ((enum clcq2_ops_e)c) + safeswitch ((enum clcq2_ops_e)c) { - default: - Con_Printf ("SVQ2_ReadClientMessage: unknown command char %i\n", c); - SV_DropClient (cl); - return; - case clcq2_nop: break; @@ -8581,6 +8589,14 @@ void SVQ2_ExecuteClientMessage (client_t *cl) SV_VoiceReadPacket(); break; #endif + + case clcq2_bad: + case clcr1q2_setting: + case clcr1q2_multimoves: + safedefault: + Con_Printf ("SVQ2_ReadClientMessage: unknown command char %i\n", c); + SV_DropClient (cl); + return; } } } @@ -8824,13 +8840,8 @@ void SVNQ_ExecuteClientMessage (client_t *cl) if (c == -1) break; - switch (c) + safeswitch (c) { - default: - Con_Printf ("SVNQ_ReadClientMessage: unknown command char %i\n", c); - SV_DropClient (cl); - return; - case clc_disconnect: host_client = cl; sv_player = cl->edict; @@ -8856,16 +8867,16 @@ void SVNQ_ExecuteClientMessage (client_t *cl) host_client->last_sequence += 0x10000; //wrapped host_client->last_sequence = (host_client->last_sequence&0xffff0000) | seq; - if (cl->lastsequence_acknowledged) + if (cl->lastsequence_acknowledged>0 && cl->netchan.incoming_sequence-cl->lastsequence_acknowledgedframeunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; + frame = &host_client->frameunion.frames[cl->lastsequence_acknowledged & UPDATE_MASK]; if (frame->ping_time == -1) - frame->ping_time = (realtime - frame->senttime) - delay; + frame->ping_time = (realtime - frame->senttime); } else { frame = &host_client->frameunion.frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; - frame->ping_time = (sv.time - cl->lastcmd.servertime/1000.0) - delay; + frame->ping_time = (sv.time - cl->lastcmd.servertime/1000.0); } frame->move_msecs = cl->lastcmd.servertime - oldservertime; if (frame->ping_time*1000 > sv_minping.value+1) @@ -8880,6 +8891,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl) if (host_client->delay > 1) host_client->delay = 1; } + frame->ping_time -= delay; } break; case clc_move: //bytes: 16(nq), 19(proquake/fitz), 56(dp7) @@ -8887,7 +8899,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl) return; //shouldn't be sending moves at this point. typically they're stale, left from the previous map. this results in crashes if the protocol is different. forceangle16 = false; - switch(cl->protocol) + safeswitch(cl->protocol) { case SCP_FITZ666: forceangle16 = true; @@ -8913,6 +8925,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl) case SCP_QUAKE3: case SCP_DARKPLACES6: case SCP_DARKPLACES7: + safedefault: break; } @@ -8968,6 +8981,11 @@ void SVNQ_ExecuteClientMessage (client_t *cl) SV_VoiceReadPacket(); break; #endif + + safedefault: + Con_Printf ("SVNQ_ReadClientMessage: unknown command char %i\n", c); + SV_DropClient (cl); + return; } } }