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:
parent
5584fb1ab1
commit
14e7517b16
17 changed files with 321 additions and 113 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue