]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
QW support getting very close
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 25 Feb 2006 13:21:54 +0000 (13:21 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 25 Feb 2006 13:21:54 +0000 (13:21 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6030 d7cf8633-e32d-0410-b094-e92efae38249

cl_input.c
cl_parse.c
client.h
common.c
common.h
host_cmd.c
netconn.c
protocol.c

index c6eb720b293b6049eed0d26acbdb61559dbf6b63..62451ea69295ac61fcfafc276060b4d3e82e628b 100644 (file)
@@ -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);
 }
 
index c0aab1f1a673b58195ce8a0f013d7311b5e0889f..f55143fcbf571859af7d8b41534cb6cf2b58a472 100644 (file)
@@ -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
index 053365afee045f0cd0b03cc40af4ea3d5d121d48..b87be4265616c3be10f623b14e7c640a90ddfba4 100644 (file)
--- 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);
index efbe9bad48dbd4e2dcb1daf5c7267d56254005bc..570b6f43c4cda58ee5a6b8f94dd0335a80feff38 100644 (file)
--- 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;
+}
 
 /*
 ==============================================================================
index 3bba8dd22fda1d6ddbf612bc6bd1c138b55c7a34..97c6e799557dc010f670fe22c802343a3192c9b6 100644 (file)
--- 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
index f10203a1bc93fed9af949d0342ce55aacc7c6c62..a3292429ad9872e4b682bbdf14f9d654b14c1454 100644 (file)
@@ -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 [ <key> <value> ]\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] == '*')
        {
index 1904813e7d4ad56f784e9648a2292e10c97317a8..0bb32463665771f8dec432abaeceace525466449 100755 (executable)
--- 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);
index 6b104129aed653cda4e0b326c43c6188c644f9a8..69b1c52b11c2bc0cca7e86666d3b7a6908443121 100644 (file)
@@ -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);
                        }
                }