From ac4cb312f454a6097b0f152c947cb8c9698d4bd1 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 25 Feb 2006 13:21:54 +0000 Subject: [PATCH] QW support getting very close git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6030 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_input.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++----- cl_parse.c | 39 +++++-------- client.h | 18 +++++- common.c | 59 +++++++++++++++++++ common.h | 2 + host_cmd.c | 18 +----- netconn.c | 13 ++--- protocol.c | 10 ++-- 8 files changed, 260 insertions(+), 68 deletions(-) diff --git a/cl_input.c b/cl_input.c index c6eb720b..62451ea6 100644 --- a/cl_input.c +++ b/cl_input.c @@ -288,6 +288,8 @@ cvar_t m_filter = {CVAR_SAVE, "m_filter","0", "smoothes mouse movement, less res cvar_t cl_netinputpacketspersecond = {CVAR_SAVE, "cl_netinputpacketspersecond","50", "how many input packets to send to server each second"}; +cvar_t cl_nodelta = {0, "cl_nodelta", "0", "disables delta compression of non-player entities in QW network protocol"}; + /* ================ @@ -513,6 +515,34 @@ void CL_UpdatePrydonCursor(void) //CL_SparkShower(cl.cmd.cursor_impact, cl.cmd.cursor_normal, 5, 0); } +void CL_ClientMovement_InputQW(qw_usercmd_t *cmd) +{ + int i; + int n; + // remove stale queue items + n = cl.movement_numqueue; + cl.movement_numqueue = 0; + for (i = 0;i < n;i++) + if (cl.movement_queue[i].sequence > cls.netcon->qw.incoming_sequence) + cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i]; + // add to input queue if there is room + if (cl.movement_numqueue < (int)(sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0])) && cl.mtime[0] > cl.mtime[1]) + { + // add to input queue + cl.movement_queue[cl.movement_numqueue].sequence = cls.netcon->qw.outgoing_sequence; + cl.movement_queue[cl.movement_numqueue].time = cl.mtime[0] + cl_movement_latency.value / 1000.0; + cl.movement_queue[cl.movement_numqueue].frametime = cmd->msec * 0.001; + VectorCopy(cmd->angles, cl.movement_queue[cl.movement_numqueue].viewangles); + cl.movement_queue[cl.movement_numqueue].move[0] = cmd->forwardmove; + cl.movement_queue[cl.movement_numqueue].move[1] = cmd->sidemove; + cl.movement_queue[cl.movement_numqueue].move[2] = cmd->upmove; + cl.movement_queue[cl.movement_numqueue].jump = (cmd->buttons & 2) != 0; + cl.movement_queue[cl.movement_numqueue].crouch = false; + cl.movement_numqueue++; + } + cl.movement_replay = true; +} + void CL_ClientMovement_Input(qboolean buttonjump, qboolean buttoncrouch) { int i; @@ -792,6 +822,48 @@ void CL_ClientMovement_Replay(void) //VectorSet(cl_entities[cl.playerentity].state_current.angles, 0, cl.viewangles[1], 0); } +void QW_MSG_WriteDeltaUsercmd(sizebuf_t *buf, qw_usercmd_t *from, qw_usercmd_t *to) +{ + int bits; + + bits = 0; + if (to->angles[0] != from->angles[0]) + bits |= QW_CM_ANGLE1; + if (to->angles[1] != from->angles[1]) + bits |= QW_CM_ANGLE2; + if (to->angles[2] != from->angles[2]) + bits |= QW_CM_ANGLE3; + if (to->forwardmove != from->forwardmove) + bits |= QW_CM_FORWARD; + if (to->sidemove != from->sidemove) + bits |= QW_CM_SIDE; + if (to->upmove != from->upmove) + bits |= QW_CM_UP; + if (to->buttons != from->buttons) + bits |= QW_CM_BUTTONS; + if (to->impulse != from->impulse) + bits |= QW_CM_IMPULSE; + + MSG_WriteByte(buf, bits); + if (bits & QW_CM_ANGLE1) + MSG_WriteAngle16i(buf, to->angles[0]); + if (bits & QW_CM_ANGLE2) + MSG_WriteAngle16i(buf, to->angles[1]); + if (bits & QW_CM_ANGLE3) + MSG_WriteAngle16i(buf, to->angles[2]); + if (bits & QW_CM_FORWARD) + MSG_WriteShort(buf, to->forwardmove); + if (bits & QW_CM_SIDE) + MSG_WriteShort(buf, to->sidemove); + if (bits & QW_CM_UP) + MSG_WriteShort(buf, to->upmove); + if (bits & QW_CM_BUTTONS) + MSG_WriteShort(buf, to->buttons); + if (bits & QW_CM_IMPULSE) + MSG_WriteShort(buf, to->impulse); + MSG_WriteByte(buf, to->msec); +} + /* ============== CL_SendMove @@ -914,7 +986,67 @@ void CL_SendMove(void) // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total // PROTOCOL_DARKPLACES7 clc_move = 56 bytes total - if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE) + if (cls.protocol == PROTOCOL_QUAKEWORLD) + { + int checksumindex; + double msectime; + static double oldmsectime; + qw_usercmd_t *cmd, *oldcmd; + qw_usercmd_t nullcmd; + + //Con_Printf("code qw_clc_move\n"); + + i = cls.netcon->qw.outgoing_sequence & QW_UPDATE_MASK; + cmd = &cl.qw_moves[i]; + memset(&nullcmd, 0, sizeof(nullcmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->buttons = bits; + cmd->impulse = impulse; + cmd->forwardmove = (short)bound(-32768, forwardmove, 32767); + cmd->sidemove = (short)bound(-32768, sidemove, 32767); + cmd->upmove = (short)bound(-32768, upmove, 32767); + VectorCopy(cl.viewangles, cmd->angles); + msectime = realtime * 1000; + cmd->msec = (unsigned char)bound(0, msectime - oldmsectime, 255); + // ridiculous value rejection (matches qw) + if (cmd->msec > 250) + cmd->msec = 100; + oldmsectime = msectime; + + CL_ClientMovement_InputQW(cmd); + + MSG_WriteByte(&buf, qw_clc_move); + // save the position for a checksum byte + checksumindex = buf.cursize; + MSG_WriteByte(&buf, 0); + // packet loss percentage + // FIXME: netgraph stuff + MSG_WriteByte(&buf, 0); + // write most recent 3 moves + i = (cls.netcon->qw.outgoing_sequence-2) & QW_UPDATE_MASK; + cmd = &cl.qw_moves[i]; + QW_MSG_WriteDeltaUsercmd(&buf, &nullcmd, cmd); + oldcmd = cmd; + i = (cls.netcon->qw.outgoing_sequence-1) & QW_UPDATE_MASK; + cmd = &cl.qw_moves[i]; + QW_MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd); + oldcmd = cmd; + i = cls.netcon->qw.outgoing_sequence & QW_UPDATE_MASK; + cmd = &cl.qw_moves[i]; + QW_MSG_WriteDeltaUsercmd(&buf, oldcmd, cmd); + // calculate the checksum + buf.data[checksumindex] = COM_BlockSequenceCRCByteQW(buf.data + checksumindex + 1, buf.cursize - checksumindex - 1, cls.netcon->qw.outgoing_sequence); + // if delta compression history overflows, request no delta + if (cls.netcon->qw.outgoing_sequence - cl.qw_validsequence >= QW_UPDATE_BACKUP-1) + cl.qw_validsequence = 0; + // request delta compression if appropriate + if (cl.qw_validsequence && !cl_nodelta.integer && cls.state == ca_connected && !cls.demorecording) + { + MSG_WriteByte(&buf, qw_clc_delta); + MSG_WriteByte(&buf, cl.qw_validsequence & 255); + } + } + else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE) { // 5 bytes MSG_WriteByte (&buf, clc_move); @@ -929,6 +1061,8 @@ void CL_SendMove(void) // 2 bytes MSG_WriteByte (&buf, bits); MSG_WriteByte (&buf, impulse); + + CL_ClientMovement_Input((bits & 2) != 0, false); } else if (cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3) { @@ -945,6 +1079,8 @@ void CL_SendMove(void) // 2 bytes MSG_WriteByte (&buf, bits); MSG_WriteByte (&buf, impulse); + + CL_ClientMovement_Input((bits & 2) != 0, false); } else if (cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5) { @@ -961,6 +1097,8 @@ void CL_SendMove(void) // 2 bytes MSG_WriteByte (&buf, bits); MSG_WriteByte (&buf, impulse); + + CL_ClientMovement_Input((bits & 2) != 0, false); } else { @@ -998,23 +1136,26 @@ void CL_SendMove(void) MSG_WriteFloat (&buf, cl.cmd.cursor_impact[1]); MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]); MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber); - } - // FIXME: bits & 16 is +button5, Nexuiz specific - CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0); + // FIXME: bits & 16 is +button5, Nexuiz specific + CL_ClientMovement_Input((bits & 2) != 0, (bits & 16) != 0); + } } - // ack the last few frame numbers - // (redundent to improve handling of client->server packet loss) - // for LATESTFRAMENUMS == 3 case this is 15 bytes - for (i = 0;i < LATESTFRAMENUMS;i++) + if (cls.protocol != PROTOCOL_QUAKEWORLD) { - if (cl.latestframenums[i] > 0) + // ack the last few frame numbers + // (redundent to improve handling of client->server packet loss) + // for LATESTFRAMENUMS == 3 case this is 15 bytes + for (i = 0;i < LATESTFRAMENUMS;i++) { - if (developer_networkentities.integer >= 1) - Con_Printf("send clc_ackframe %i\n", cl.latestframenums[i]); - MSG_WriteByte(&buf, clc_ackframe); - MSG_WriteLong(&buf, cl.latestframenums[i]); + if (cl.latestframenums[i] > 0) + { + if (developer_networkentities.integer >= 1) + Con_Printf("send clc_ackframe %i\n", cl.latestframenums[i]); + MSG_WriteByte(&buf, clc_ackframe); + MSG_WriteLong(&buf, cl.latestframenums[i]); + } } } @@ -1126,5 +1267,7 @@ void CL_InitInput (void) Cvar_RegisterVariable(&m_filter); Cvar_RegisterVariable(&cl_netinputpacketspersecond); + + Cvar_RegisterVariable(&cl_nodelta); } diff --git a/cl_parse.c b/cl_parse.c index c0aab1f1..f55143fc 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -455,8 +455,8 @@ static void QW_CL_RequestNextDownload(void) // done checking sounds and models, send a prespawn command now MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); // FIXME: calculate the checksum2 this wants - //MSG_WriteString(&cls.netcon->message, va(qw_prespawn_name, cl.qw_servercount, cl.worldmodel->checksum2)); - MSG_WriteString(&cls.netcon->message, va(qw_prespawn_name, cl.qw_servercount, 0)); + //MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, cl.worldmodel->checksum2)); + MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, 0)); if (cls.qw_downloadmemory) { @@ -478,7 +478,7 @@ static void QW_CL_RequestNextDownload(void) if (cl.sound_name[cls.qw_downloadnumber][0] == '*') continue; // check if we need to download the file, and return if so - if (!QW_CL_CheckOrDownloadFile(cl.sound_name[cls.qw_downloadnumber])) + if (!QW_CL_CheckOrDownloadFile(va("sound/%s", cl.sound_name[cls.qw_downloadnumber]))) return; } @@ -504,7 +504,7 @@ static void QW_CL_RequestNextDownload(void) // done with sound downloads, next we check models MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); - MSG_WriteString(&cls.netcon->message, va(qw_modellist_name, cl.qw_servercount, 0)); + MSG_WriteString(&cls.netcon->message, va("modellist %i %i", cl.qw_servercount, 0)); break; case dl_none: default: @@ -597,9 +597,10 @@ static void QW_CL_ParseModelList(void) } n = MSG_ReadByte(); + if (n) { MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); - MSG_WriteString(&cls.netcon->message, va(qw_modellist_name, cl.qw_servercount, n)); + MSG_WriteString(&cls.netcon->message, va("modellist %i %i", cl.qw_servercount, n)); return; } @@ -633,7 +634,7 @@ static void QW_CL_ParseSoundList(void) if (n) { MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); - MSG_WriteString(&cls.netcon->message, va(qw_soundlist_name, cl.qw_servercount, n)); + MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, n)); return; } @@ -933,21 +934,14 @@ void CL_ParseServerInfo (void) } #endif - // parse maxclients - cl.maxclients = MSG_ReadByte (); - if (cl.maxclients & 128) - { - cl.qw_spectator = true; - cl.maxclients &= ~128; - } - if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) - { - Host_Error("Bad maxclients (%u) from server", cl.maxclients); - return; - } - cl.scores = (scoreboard_t *)Mem_Alloc(cl_mempool, cl.maxclients*sizeof(*cl.scores)); - cl.gametype = GAME_DEATHMATCH; + cl.maxclients = 32; + + // parse player number + i = MSG_ReadByte(); + cl.qw_spectator = (i & 128) != 0; + cl.playerentity = cl.viewentity = (i & 127) + 1; + cl.scores = (scoreboard_t *)Mem_Alloc(cl_mempool, cl.maxclients*sizeof(*cl.scores)); // get the full level name str = MSG_ReadString (); @@ -984,7 +978,7 @@ void CL_ParseServerInfo (void) memset(cl.sound_precache, 0, sizeof(cl.sound_precache)); MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); - MSG_WriteString(&cls.netcon->message, va(qw_soundlist_name, cl.qw_servercount, 0)); + MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0)); cls.state = ca_connected; cls.signon = 1; @@ -2371,8 +2365,7 @@ void CL_ParseServerMessage(void) break; case qw_svc_cdtrack: - cl.cdtrack = MSG_ReadByte (); - cl.looptrack = MSG_ReadByte (); + cl.cdtrack = cl.looptrack = MSG_ReadByte (); if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) CDAudio_Play ((unsigned char)cls.forcetrack, true); else diff --git a/client.h b/client.h index 053365af..b87be426 100644 --- a/client.h +++ b/client.h @@ -523,6 +523,18 @@ typedef struct qboolean drawcrosshair; }csqc_vidvars_t; +typedef struct qw_usercmd_s +{ + vec3_t angles; + short forwardmove, sidemove, upmove; + unsigned char padding1[2]; + unsigned char msec; + unsigned char buttons; + unsigned char impulse; + unsigned char padding2; +} +qw_usercmd_t; + // // the client_state_t structure is wiped completely at every // server signon @@ -730,6 +742,10 @@ typedef struct client_state_s // 255 is the most nails the QW protocol could send int qw_num_nails; vec_t qw_nails[255][6]; + + int qw_validsequence; + + qw_usercmd_t qw_moves[QW_UPDATE_BACKUP]; } client_state_t; @@ -827,8 +843,6 @@ extern int cl_num_static_entities; extern int cl_num_temp_entities; extern int cl_num_brushmodel_entities; -extern char qw_emodel_name[], qw_pmodel_name[], qw_prespawn_name[], qw_modellist_name[], qw_soundlist_name[]; - extern client_state_t cl; extern void CL_AllocDlight (entity_render_t *ent, matrix4x4_t *matrix, float radius, float red, float green, float blue, float decay, float lifetime, int cubemapnum, int style, int shadowenable, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags); diff --git a/common.c b/common.c index efbe9bad..570b6f43 100644 --- a/common.c +++ b/common.c @@ -177,6 +177,65 @@ unsigned short CRC_Block(const unsigned char *data, size_t size) return crc ^ CRC_XOR_VALUE; } +// QuakeWorld +static unsigned char chktbl[1024 + 4] = +{ + 0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01, + 0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a, + 0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58, + 0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3, + 0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b, + 0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36, + 0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8, + 0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27, + 0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd, + 0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63, + 0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2, + 0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d, + 0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65, + 0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f, + 0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f, + 0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42, + 0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59, + 0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9, + 0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69, + 0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba, + 0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85, + 0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4, + 0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8, + 0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa, + 0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05, + 0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7, + 0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a, + 0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb, + 0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b, + 0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d, + 0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce, + 0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3, + + // map checksum goes here + 0x00,0x00,0x00,0x00 +}; + +// QuakeWorld +unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence) +{ + unsigned char *p; + unsigned char chkb[60 + 4]; + + p = chktbl + (sequence % (sizeof(chktbl) - 8)); + + if (length > 60) + length = 60; + memcpy(chkb, base, length); + + chkb[length] = (sequence & 0xff) ^ p[0]; + chkb[length+1] = p[1]; + chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2]; + chkb[length+3] = p[3]; + + return CRC_Block(chkb, length + 4) & 0xff; +} /* ============================================================================== diff --git a/common.h b/common.h index 3bba8dd2..97c6e799 100644 --- a/common.h +++ b/common.h @@ -61,6 +61,8 @@ void Com_HexDumpToConsole(const unsigned char *data, int size); unsigned short CRC_Block(const unsigned char *data, size_t size); +unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence); + //============================================================================ // Endianess handling diff --git a/host_cmd.c b/host_cmd.c index f10203a1..a3292429 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -1957,20 +1957,6 @@ static void MaxPlayers_f(void) // QuakeWorld commands -char qw_emodel_name[] = - { 'e' ^ 0xff, 'm' ^ 0xff, 'o' ^ 0xff, 'd' ^ 0xff, 'e' ^ 0xff, 'l' ^ 0xff, 0 }; -char qw_pmodel_name[] = - { 'p' ^ 0xff, 'm' ^ 0xff, 'o' ^ 0xff, 'd' ^ 0xff, 'e' ^ 0xff, 'l' ^ 0xff, 0 }; -char qw_prespawn_name[] = - { 'p'^0xff, 'r'^0xff, 'e'^0xff, 's'^0xff, 'p'^0xff, 'a'^0xff, 'w'^0xff, 'n'^0xff, - ' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '0'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 }; -char qw_modellist_name[] = - { 'm'^0xff, 'o'^0xff, 'd'^0xff, 'e'^0xff, 'l'^0xff, 'l'^0xff, 'i'^0xff, 's'^0xff, 't'^0xff, - ' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 }; -char qw_soundlist_name[] = - { 's'^0xff, 'o'^0xff, 'u'^0xff, 'n'^0xff, 'd'^0xff, 'l'^0xff, 'i'^0xff, 's'^0xff, 't'^0xff, - ' '^0xff, '%'^0xff, 'i'^0xff, ' '^0xff, '%'^0xff, 'i'^0xff, 0 }; - /* ===================== Host_Rcon_f @@ -2146,7 +2132,7 @@ void Host_FullInfo_f (void) // credit: taken from QuakeWorld if (*s) s++; - if (!strcasecmp(key, qw_pmodel_name) || !strcasecmp(key, qw_emodel_name)) + if (!strcasecmp(key, "pmodel") || !strcasecmp(key, "emodel")) continue; if (key[0] == '*') @@ -2178,7 +2164,7 @@ void Host_SetInfo_f (void) // credit: taken from QuakeWorld Con_Printf ("usage: setinfo [ ]\n"); return; } - if (!strcasecmp(Cmd_Argv(1), qw_pmodel_name) || !strcasecmp(Cmd_Argv(1), qw_emodel_name)) + if (!strcasecmp(Cmd_Argv(1), "pmodel") || !strcasecmp(Cmd_Argv(1), "emodel")) return; if (Cmd_Argv(1)[0] == '*') { diff --git a/netconn.c b/netconn.c index 1904813e..0bb32463 100755 --- a/netconn.c +++ b/netconn.c @@ -439,11 +439,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers int packetLen; qboolean sendreliable; - if (data->cursize == 0 && conn->message.cursize == 0) - { - Con_Printf ("Datagram_SendUnreliableMessage: zero length message\n"); - return -1; - } + // note that it is ok to send empty messages to the qw server, + // otherwise it won't respond to us at all sendreliable = false; // if the remote side dropped the last reliable message, resend it @@ -823,8 +820,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len } packetsReceived++; - reliable_message = sequence >> 31; - reliable_ack = sequence_ack >> 31; + reliable_message = (sequence >> 31) & 1; + reliable_ack = (sequence_ack >> 31) & 1; sequence &= ~(1<<31); sequence_ack &= ~(1<<31); if (sequence <= conn->qw.incoming_sequence) @@ -1069,7 +1066,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat NetConn_WriteString(mysocket, va("\377\377\377\377connect\\protocol\\darkplaces 3\\protocols\\%s\\challenge\\%s", protocolnames, string + 10), peeraddress); return true; } - if (length > 1 && string[0] == 'c' && string[1] >= '0' && string[1] <= '9') + if (length > 1 && string[0] == 'c' && (string[1] == '-' || (string[1] >= '0' && string[1] <= '9'))) { // quakeworld LHNETADDRESS_ToString(peeraddress, addressstring2, sizeof(addressstring2), true); diff --git a/protocol.c b/protocol.c index 6b104129..69b1c52b 100644 --- a/protocol.c +++ b/protocol.c @@ -2558,7 +2558,7 @@ static void EntityStateQW_ReadEntityUpdate(entity_state_t *s, int bits) void EntityFrameQW_CL_ReadFrame(qboolean delta) { qboolean invalid = false; - int i, number, oldsnapindex, newsnapindex, oldindex, newindex, oldnum, newnum; + int number, oldsnapindex, newsnapindex, oldindex, newindex, oldnum, newnum; entity_t *ent; entityframeqw_database_t *d = cl.entitydatabaseqw; entityframeqw_snapshot_t *oldsnap, *newsnap; @@ -2584,11 +2584,9 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) } // read the number of this frame to echo back in next input packet - for (i = 0;i < LATESTFRAMENUMS-1;i++) - cl.latestframenums[i] = cl.latestframenums[i+1]; - cl.latestframenums[LATESTFRAMENUMS-1] = cls.netcon->qw.incoming_sequence; + cl.qw_validsequence = cls.netcon->qw.incoming_sequence; if (invalid) - cl.latestframenums[LATESTFRAMENUMS-1] = 0; + cl.qw_validsequence = 0; // read entity numbers until we find a 0x0000 // (which would be an empty update on world entity, but is actually a terminator) @@ -2632,7 +2630,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) { if (newnum != oldnum && !delta && !invalid) { - cl.latestframenums[LATESTFRAMENUMS-1] = 0; + cl.qw_validsequence = 0; Con_Printf("WARNING: U_REMOVE %i on full update\n", newnum); } } -- 2.39.2