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
This commit is contained in:
Spoike 2021-08-04 21:16:57 +00:00
parent 5584fb1ab1
commit 14e7517b16
17 changed files with 321 additions and 113 deletions

View file

@ -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

View file

@ -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))
{

View file

@ -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);

View file

@ -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<<i))
newbase[i] = MSG_ReadShort();
else
newbase[i] = 0;
diff[i] = newbase[i]-cl.playerview[seat].baseangles[i];
cl.playerview[seat].baseangles[i] = newbase[i];
if (fl & 8) //locking the view
newang[i] = SHORT2ANGLE(newbase[i]);
else //free-look
newang[i] = cl.playerview[seat].viewangles[i] + SHORT2ANGLE(diff[i]);
}
if (cl.ackedmovesequence)
{
//tweak all unacked input frames to the new base. the server will do similar on receipt of them.
i = min(64, cl.movesequence-cl.ackedmovesequence);
for (i = cl.movesequence-i; i < cl.movesequence; i++)
{
cl.outframes[i & UPDATE_MASK].cmd[seat].angles[0] += diff[0];
cl.outframes[i & UPDATE_MASK].cmd[seat].angles[1] += diff[1];
cl.outframes[i & UPDATE_MASK].cmd[seat].angles[2] += diff[2];
}
}
if (!CSQC_Parse_SetAngles(seat, newang, false))
{
if (fl & 8)
{
inf->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))

View file

@ -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;

View file

@ -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<<i))
{
if (bits & UC_ABSANG)
MSG_WriteShort(buf, cmd->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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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<<i;
else
to->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<<i;
}
@ -845,15 +849,15 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
if (bits & U_EFFECTS)
MSG_WriteByte (msg, to->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<<j);
if (ackedframe->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<<j))
MSG_WriteShort(msg, seat->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

View file

@ -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;

View file

@ -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;
}

View file

@ -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.
}

View file

@ -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_acknowledged<UPDATE_BACKUP)
{
/*note that if there is packetloss, we can change a single frame's ping_time multiple times
this means that the 'ping' is more latency than ping times*/
if (frame->ping_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_acknowledged<UPDATE_BACKUP)
{
frame = &host_client->frameunion.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;
}
}
}