Attempt to work around a DP client bug, where DP sends either 16bit or 8bit angles depending upon the type of the previous server that DP connected to.

Fixed weirdness around a second DP client bug (less serious) where a reconnecting DP client sends a disconnect request as soon as it gets its new connection. The client will still get disconnected (as per its apparent request), but FTE will no longer alarm admins, and the user should see something like 'unconnected dropped'.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5219 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-03-05 11:06:12 +00:00
parent 0da0e97fc5
commit 42b31a6cc3
4 changed files with 60 additions and 12 deletions

View File

@ -183,7 +183,7 @@ typedef struct
int isnqprotocol;
qboolean nqreliable_allowed; //says the peer has acked the last reliable (or timed out and needs resending).
float nqreliable_resendtime;//force nqreliable_allowed, thereby forcing a resend of anything n
qbyte nqunreliableonly; //nq can't cope with certain reliables some times. if 2, we have a reliable that result in a block (that should be sent). if 1, we are blocking. if 0, we can send reliables freely.
qbyte nqunreliableonly; //nq can't cope with certain reliables some times. if 2, we have a reliable that result in a block (that should be sent). if 1, we are blocking. if 0, we can send reliables freely. if 3, then we just want to ignore clc_moves
#endif
struct netprim_s netprim;
int fragmentsize;

View File

@ -627,8 +627,9 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
chan->nqreliable_allowed = false;
chan->nqreliable_resendtime = realtime + 0.3; //resend reliables after 0.3 seconds. nq transports suck.
if (NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address) == NETERR_SENT && NET_AddrIsReliable(&chan->remote_address))
{ //if over tcp, everything is assumed to be reliable. pretend it got acked now.
if (NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address) == NETERR_SENT && (
NET_AddrIsReliable(&chan->remote_address) || chan->nqunreliableonly==3 ))
{ //if over tcp (or we're dropping the connection), everything is assumed to be reliable. pretend it got acked now.
//if we get an ack later, then who cares.
chan->reliable_start += i;
if (chan->reliable_start >= chan->reliable_length)

View File

@ -716,6 +716,14 @@ void SV_DropClient (client_t *drop)
}
if (drop->netchan.remote_address.type != NA_INVALID && drop->netchan.message.maxsize)
{
#ifdef NQPROT
if (drop->netchan.isnqprotocol && drop->netchan.nqunreliableonly != 1)
{ //try and flush the reliables, so they can see why they were kicked.
drop->netchan.nqunreliableonly = 3; //may cause problems if they were loading content. not much we can do about that.
while(Netchan_Transmit (&drop->netchan, 0, NULL, 10000))
;
}
#endif
//send twice, to cover packetloss a little.
Netchan_Transmit (&drop->netchan, termmsg.cursize, termmsg.data, 10000);
Netchan_Transmit (&drop->netchan, termmsg.cursize, termmsg.data, 10000);
@ -2445,7 +2453,6 @@ client_t *SVC_DirectConnect(void)
if (p == countof(dpnames))
Con_DPrintf("DP client reporting unknown protocol \"%s\"\n", com_token);
}
proquakeanglehack = false;
protocol = SCP_DARKPLACES7;
@ -2464,7 +2471,9 @@ client_t *SVC_DirectConnect(void)
Info_SetValueForKey(userinfo[0], "name", "CONNECTING", sizeof(userinfo[0]));
qport = 0;
proquakeanglehack = true;
proquakeanglehack = false; //NOTE: DP clients fuck up here due to a DP client bug.
//DP clients will use 16bit angles if it has previously connected to a proquake-handshake server,
//and 8bit angles otherwise (or a non-proquake/non-dp/non-qw server more recently than the proquake one).
}
else
{

View File

@ -483,6 +483,8 @@ void SVNQ_New_f (void)
}
return;
}
if (host_client->drop)
return;
if (!host_client->pextknown && sv_listen_nq.ival != 1) //1 acts as a legacy mode, used for clients that can't cope with cmd before serverdata (either because they crash out or because they refuse to send reliables until after they got the first serverdata)
{
@ -8071,7 +8073,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
}
#endif
#ifdef NQPROT
void SVNQ_ReadClientMove (usercmd_t *move)
void SVNQ_ReadClientMove (usercmd_t *move, qboolean forceangle16)
{
int i;
int bits;
@ -8104,7 +8106,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
move->fservertime = cltime;
move->servertime = move->fservertime*1000;
frame->ping_time = sv.time - cltime;
frame->ping_time = sv.time - cltime;
if (frame->ping_time*1000 > sv_minping.value+1)
@ -8124,7 +8126,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
// read current angles
for (i=0 ; i<3 ; i++)
{
if (host_client->protocol == SCP_FITZ666 || (host_client->proquake_angles_hack && (host_client->protocol == SCP_NETQUAKE || host_client->protocol == SCP_BJP3)))
if (forceangle16)
host_client->edict->v->v_angle[i] = MSG_ReadAngle16 ();
else
host_client->edict->v->v_angle[i] = MSG_ReadAngle ();
@ -8259,6 +8261,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
int c;
char *s;
// client_frame_t *frame;
qboolean forceangle16;
cl->netchan.outgoing_sequence++;
cl->netchan.incoming_acknowledged = cl->netchan.outgoing_sequence-1;
@ -8315,14 +8318,44 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
case clc_nop:
break;
// case clc_delta:
// case clc_delta: //not in NQ
// cl->delta_sequence = MSG_ReadByte ();
// break;
case clc_move:
if (cl->netchan.nqunreliableonly || cl->prespawn_stage == PRESPAWN_PROTOCOLSWITCH)
case clc_move: //bytes: 16(nq), 19(proquake/fitz), 56(dp7)
if (cl->state != cs_spawned)
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.
SVNQ_ReadClientMove (&host_client->lastcmd);
forceangle16 = false;
switch(cl->protocol)
{
case SCP_FITZ666:
forceangle16 = true;
break;
case SCP_NETQUAKE:
case SCP_BJP3:
//Hack to work around buggy DP clients that don't reset the proquake hack for the next server
//this ONLY works because the other clc commands are very unlikely to both be 3 bytes big and sent unreliably
//aka: DP ProQuake angles hack hack
//note that if a client then decides to use 16bit coords because of this hack then it would be the 'fte dp proquake angles hack hack hack'....
if ((net_message.cursize-(msg_readcount-1) == 16 && cl->proquake_angles_hack) ||
(net_message.cursize-(msg_readcount-1) == 19 && !cl->proquake_angles_hack))
{
cl->proquake_angles_hack ^= 1;
SV_ClientPrintf(cl, PRINT_HIGH, "Client sent "S_COLOR_RED"wrong"S_COLOR_WHITE" clc_move size, switching to %u-bit angles to try to compensate\n", cl->proquake_angles_hack?16:8);
}
forceangle16 = cl->proquake_angles_hack;
break;
case SCP_BAD:
case SCP_QUAKEWORLD:
case SCP_QUAKE2:
case SCP_QUAKE3:
case SCP_DARKPLACES6:
case SCP_DARKPLACES7:
break;
}
SVNQ_ReadClientMove (&cl->lastcmd, forceangle16);
// cmd = host_client->lastcmd;
// SV_ClientThink();
break;
@ -8339,6 +8372,11 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
case clcfte_qcrequest:
SV_ReadQCRequest();
host_client = cl;
sv_player = cl->edict;
if (cl->state < cs_connected)
return;
break;
case clcdp_ackframe: