From 776faf1bc4827488cfd192190fe2179b67743ac0 Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 9 Jan 2008 00:52:31 +0000 Subject: [PATCH] Added initial support for eztv extensions. This is the bulk of the changes. Downloading isn't implemented yet though. Also fixed some demo playback sbar stats, and fixed NQ demo playback. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2852 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cam.c | 4 +- engine/client/cl_demo.c | 233 +++++++++++++++++++++++---------------- engine/client/cl_ents.c | 6 +- engine/client/cl_input.c | 45 +++++--- engine/client/cl_main.c | 8 +- engine/client/cl_parse.c | 144 ++++++++++++++++-------- engine/client/cl_pred.c | 23 +++- engine/client/client.h | 2 +- engine/client/keys.c | 2 +- 9 files changed, 294 insertions(+), 173 deletions(-) diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 99d873017..b35ee73c1 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -163,7 +163,7 @@ void Cam_Lock(int pnum, int playernum) Skin_FlushPlayers(); - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { memcpy(&cl.stats[pnum], cl.players[playernum].stats, sizeof(cl.stats[pnum])); } @@ -569,7 +569,7 @@ void Cam_FinishMove(int pnum, usercmd_t *cmd) if (cls.state != ca_active) return; - if (!cl.spectator && cls.demoplayback != DPB_MVD) // only in spectator mode + if (!cl.spectator && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) // only in spectator mode return; if (cmd->buttons & BUTTON_ATTACK) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index d745c42ea..b42ceb6e8 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -31,13 +31,15 @@ void CL_PlayDemo(char *demoname); char lastdemoname[256]; extern cvar_t qtvcl_forceversion1; +extern cvar_t qtvcl_eztvextensions; unsigned char demobuffer[1024*16]; int demobuffersize; int demopreparsedbytes; qboolean disablepreparse; +qboolean endofdemo; -#define BUFFERTIME 0.1 +#define BUFFERTIME 0.5 /* ============================================================================== @@ -161,7 +163,7 @@ int demo_preparsedemo(unsigned char *buffer, int bytes) int ofs; unsigned int length; #define dem_mask 7 - if (cls.demoplayback != DPB_MVD) + if (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV) return bytes; //no need if its not an mvd (this simplifies it a little) while (bytes>2) @@ -246,7 +248,7 @@ int readdemobytes(int *readpos, void *data, int len) else if (i < 0) { //0 means no data available yet printf("VFS_READ failed\n"); -// CL_StopPlayback(); + endofdemo = true; return 0; } @@ -255,6 +257,7 @@ int readdemobytes(int *readpos, void *data, int len) if (len > demobuffersize) { len = demobuffersize; + return 0; } memcpy(data, demobuffer+*readpos, len); *readpos += len; @@ -274,10 +277,14 @@ void demo_flushcache(void) { demobuffersize = 0; demopreparsedbytes = 0; + + //no errors yet + disablepreparse = false; } void demo_resetcache(int bytes, void *data) { + endofdemo = false; demo_flushcache(); demobuffersize = bytes; @@ -373,6 +380,13 @@ qboolean CL_GetDemoMessage (void) int demopos = 0; int msglength; + if (endofdemo) + { + endofdemo = false; + CL_StopPlayback (); + return 0; + } + #ifdef NQPROT if (cls.demoplayback == DPB_NETQUAKE #ifdef Q2CLIENT @@ -451,6 +465,7 @@ qboolean CL_GetDemoMessage (void) { return 0; } + demo_flushbytes(demopos); net_message.cursize = msglength; return 1; @@ -458,7 +473,7 @@ qboolean CL_GetDemoMessage (void) #endif readnext: // read the time from the packet - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { if (realtime < 0) { @@ -517,7 +532,7 @@ readnext: else realtime = demotime; // we're warping - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { if (msecsadded || cls.netchan.incoming_sequence < 2) { @@ -633,7 +648,7 @@ readit: } net_message.cursize = msglength; - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { switch(cls_lasttype) { @@ -665,7 +680,7 @@ readit: readdemobytes (&demopos, &i, 4); cls.netchan.incoming_sequence = LittleLong(i); - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) cls.netchan.incoming_acknowledged = cls.netchan.incoming_sequence; goto readnext; @@ -1449,7 +1464,7 @@ void CL_PlayDemo(char *demoname) TP_ExecTrigger ("f_demostart"); } -void CL_QTVPlay (vfsfile_t *newf) +void CL_QTVPlay (vfsfile_t *newf, qboolean iseztv) { CL_Disconnect_f (); @@ -1457,7 +1472,11 @@ void CL_QTVPlay (vfsfile_t *newf) demo_flushcache(); //just in case - cls.demoplayback = DPB_MVD; + if (iseztv) + cls.demoplayback = DPB_EZTV; + else + cls.demoplayback = DPB_MVD; + cls.findtrack = true; cls.state = ca_demostart; @@ -1466,7 +1485,8 @@ void CL_QTVPlay (vfsfile_t *newf) realtime = -BUFFERTIME; cl.gametime = -BUFFERTIME; cl.gametimemark = realtime; - Con_Printf("Buffering for %i seconds\n", (int)-realtime); + if (realtime < -0.5) + Con_Printf("Buffering for %i seconds\n", (int)-realtime); cls.netchan.last_received=realtime; @@ -1474,6 +1494,18 @@ void CL_QTVPlay (vfsfile_t *newf) TP_ExecTrigger ("f_demostart"); } +void CL_Demo_ClientCommand(char *commandtext) +{ + unsigned char b = 1; + unsigned short len = LittleShort(strlen(commandtext) + 4); +#ifndef _MSC_VER +#warning "this needs buffering safely" +#endif + VFS_WRITE(cls.demofile, &len, sizeof(len)); + VFS_WRITE(cls.demofile, &b, sizeof(b)); + VFS_WRITE(cls.demofile, commandtext, strlen(commandtext)+1); +} + char qtvhostname[1024]; char qtvrequestbuffer[4096]; int qtvrequestsize; @@ -1494,6 +1526,7 @@ void CL_QTVPoll (void) int numviewers = 0; qboolean init_numplayers = false; qboolean init_numviewers = false; + qboolean iseztv = false; char srchost[256]; @@ -1548,88 +1581,98 @@ void CL_QTVPoll (void) *e = '\0'; colon = strchr(s, ':'); if (colon) - { *colon++ = '\0'; - if (!strcmp(s, "PERROR")) - { //printable error - Con_Printf("QTV Error:\n%s\n", colon); - } - else if (!strcmp(s, "PRINT")) - { //printable error - Con_Printf("QTV:\n%s\n", colon); - } - else if (!strcmp(s, "TERROR")) - { //printable error - Con_Printf("QTV Error:\n%s\n", colon); - } - else if (!strcmp(s, "ADEMO")) - { //printable error - Con_Printf("Demo%s is available\n", colon); - } - - //generic sourcelist responce - else if (!strcmp(s, "ASOURCE")) - { //printable source - if (!saidheader) - { - saidheader=true; - Con_Printf("Available Sources:\n"); - } - Con_Printf("%s\n", colon); - //we're too lazy to even try and parse this - } - - //v1.1 sourcelist responce includes SRCSRV, SRCHOST, SRCPLYRS, SRCVIEWS, SRCID - else if (!strcmp(s, "SRCSRV")) - { - //the proxy's source string (beware of file:blah without file:blah@blah) - } - else if (!strcmp(s, "SRCHOST")) - { - //the hostname from the server the stream came from - Q_strncpyz(srchost, colon, sizeof(srchost)); - } - else if (!strcmp(s, "SRCPLYRS")) - { - //number of active players actually playing on that stream - numplayers = atoi(colon); - init_numplayers = true; - } - else if (!strcmp(s, "SRCVIEWS")) - { - //number of people watching this stream on the proxy itself - numviewers = atoi(colon); - init_numviewers = true; - } - else if (!strcmp(s, "SRCID")) - { - streamid = atoi(colon); - - //now put it on a menu - if (!sourcesmenu) - { - m_state = m_complex; - key_dest = key_menu; - sourcesmenu = M_CreateMenu(0); - - MC_AddPicture(sourcesmenu, 16, 4, "gfx/qplaque.lmp"); - MC_AddCenterPicture(sourcesmenu, 4, "gfx/p_option.lmp"); - } - if (init_numplayers == true && init_numviewers == true) - MC_AddConsoleCommand(sourcesmenu, 42, (sourcenum++)*8 + 32, va("%s (p%i, v%i)", srchost, numplayers, numviewers), va("qtvplay %i@%s\n", streamid, qtvhostname)); - //else - // FIXME: add error message here - } - //end of sourcelist entry - - else if (!strcmp(s, "BEGIN")) - streamavailable = true; - } else - { - if (!strcmp(s, "BEGIN")) - streamavailable = true; + colon = ""; + + if (!strcmp(s, "PERROR")) + { //printable error + Con_Printf("QTV Error:\n%s\n", colon); } + else if (!strcmp(s, "PRINT")) + { //printable error + Con_Printf("QTV:\n%s\n", colon); + } + else if (!strcmp(s, "TERROR")) + { //printable error + Con_Printf("QTV Error:\n%s\n", colon); + } + else if (!strcmp(s, "ADEMO")) + { //printable error + Con_Printf("Demo%s is available\n", colon); + } + + //generic sourcelist responce + else if (!strcmp(s, "ASOURCE")) + { //printable source + if (!saidheader) + { + saidheader=true; + Con_Printf("Available Sources:\n"); + } + Con_Printf("%s\n", colon); + //we're too lazy to even try and parse this + } + + else if (!strcmp(s, "BEGIN")) + { + if (*colon) + Con_Printf("streaming \"%s\" from qtv\n", colon); + else + Con_Printf("qtv connection established\n", colon); + streamavailable = true; + } + + //eztv extensions to v1.0 + else if (!strcmp(s, "QTV_EZQUAKE_EXT")) + { + iseztv = true; + Con_Printf("Warning: eztv extensions %s\n", colon); + } + + //v1.1 sourcelist response includes SRCSRV, SRCHOST, SRCPLYRS, SRCVIEWS, SRCID + else if (!strcmp(s, "SRCSRV")) + { + //the proxy's source string (beware of file:blah without file:blah@blah) + } + else if (!strcmp(s, "SRCHOST")) + { + //the hostname from the server the stream came from + Q_strncpyz(srchost, colon, sizeof(srchost)); + } + else if (!strcmp(s, "SRCPLYRS")) + { + //number of active players actually playing on that stream + numplayers = atoi(colon); + init_numplayers = true; + } + else if (!strcmp(s, "SRCVIEWS")) + { + //number of people watching this stream on the proxy itself + numviewers = atoi(colon); + init_numviewers = true; + } + else if (!strcmp(s, "SRCID")) + { + streamid = atoi(colon); + + //now put it on a menu + if (!sourcesmenu) + { + m_state = m_complex; + key_dest = key_menu; + sourcesmenu = M_CreateMenu(0); + + MC_AddPicture(sourcesmenu, 16, 4, "gfx/qplaque.lmp"); + MC_AddCenterPicture(sourcesmenu, 4, "gfx/p_option.lmp"); + } + if (init_numplayers == true && init_numviewers == true) + MC_AddConsoleCommand(sourcesmenu, 42, (sourcenum++)*8 + 32, va("%s (p%i, v%i)", srchost, numplayers, numviewers), va("qtvplay %i@%s\n", streamid, qtvhostname)); + //else + // FIXME: add error message here + } + //end of sourcelist entry + //from e to s, we have a line s = e+1; } @@ -1638,7 +1681,7 @@ void CL_QTVPoll (void) if (streamavailable) { - CL_QTVPlay(qtvrequest); + CL_QTVPlay(qtvrequest, iseztv); qtvrequest = NULL; demo_resetcache(qtvrequestsize - (tail-qtvrequestbuffer), tail); return; @@ -1767,7 +1810,13 @@ void CL_QTVPlay_f (void) } VFS_WRITE(newf, connrequest, strlen(connrequest)); - if (raw) + + if (qtvcl_eztvextensions.value) + { + connrequest = "QTV_EZQUAKE_EXT: 3\n"; + VFS_WRITE(newf, connrequest, strlen(connrequest)); + } + else if (raw) { connrequest = "RAW: 1\n"; VFS_WRITE(newf, connrequest, strlen(connrequest)); @@ -1791,7 +1840,7 @@ void CL_QTVPlay_f (void) if (raw) { - CL_QTVPlay(newf); + CL_QTVPlay(newf, false); } else { diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 054576ce2..400996294 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -458,7 +458,7 @@ void CL_ParsePacketEntities (qboolean delta) // Con_Printf("%i %i from %i\n", cls.netchan.outgoing_sequence, cls.netchan.incoming_sequence, from); oldpacket = cl.frames[newpacket].delta_sequence; - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) from = oldpacket = cls.netchan.incoming_sequence - 1; if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >= UPDATE_BACKUP - 1) { @@ -1548,7 +1548,7 @@ void CL_LinkPacketEntities (void) CL_CalcClientTime(); servertime = cl.servertime; - pack = CL_ProcessPacketEntities(&servertime, !!cl_nolerp.value && cls.demoplayback != DPB_MVD); + pack = CL_ProcessPacketEntities(&servertime, !!cl_nolerp.value && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV && cls.demoplayback != DPB_NETQUAKE)); if (!pack) return; @@ -2317,7 +2317,7 @@ void CL_ParsePlayerinfo (void) oldstate = &cl.frames[oldparsecountmod].playerstate[num]; state = &cl.frames[parsecountmod].playerstate[num]; - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { player_state_t *prevstate, dummy; if (!cl.parsecount || info->prevcount > cl.parsecount || cl.parsecount - info->prevcount >= UPDATE_BACKUP - 1) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index d6937fc6c..c9dfe7880 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -902,7 +902,7 @@ void VARGS CL_SendClientCommand(qboolean reliable, char *format, ...) char string[2048]; clcmdbuf_t *buf, *prev; - if (cls.demoplayback) + if (cls.demoplayback && cls.demoplayback != DPB_EZTV) return; //no point. va_start (argptr, format); @@ -1218,12 +1218,13 @@ void CL_SendCmd (double frametime) int clientcount; extern cvar_t cl_maxfps; + clcmdbuf_t *next; CL_ProxyMenuHooks(); if (cls.demoplayback != DPB_NONE) { - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { extern cvar_t cl_splitscreen; i = cls.netchan.outgoing_sequence & UPDATE_MASK; @@ -1260,6 +1261,15 @@ void CL_SendCmd (double frametime) Cam_FinishMove(plnum, cmd); } + while (clientcmdlist) + { + next = clientcmdlist->next; + CL_Demo_ClientCommand(clientcmdlist->command); + Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); + Z_Free(clientcmdlist); + clientcmdlist = next; + } + cls.netchan.outgoing_sequence++; } @@ -1270,25 +1280,24 @@ void CL_SendCmd (double frametime) buf.cursize = 0; buf.data = data; CL_SendDownloadReq(&buf); + + + while (clientcmdlist) { - clcmdbuf_t *next; - while (clientcmdlist) + next = clientcmdlist->next; + if (clientcmdlist->reliable) { - next = clientcmdlist->next; - if (clientcmdlist->reliable) - { - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - MSG_WriteString (&cls.netchan.message, clientcmdlist->command); - } - else - { - MSG_WriteByte (&buf, clc_stringcmd); - MSG_WriteString (&buf, clientcmdlist->command); - } - Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); - Z_Free(clientcmdlist); - clientcmdlist = next; + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + MSG_WriteString (&cls.netchan.message, clientcmdlist->command); } + else + { + MSG_WriteByte (&buf, clc_stringcmd); + MSG_WriteString (&buf, clientcmdlist->command); + } + Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); + Z_Free(clientcmdlist); + clientcmdlist = next; } if (msecs>150) //q2 has 200 slop. diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 013a3eee3..25e5118f0 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -74,6 +74,7 @@ cvar_t cl_solid_players = SCVAR("cl_solid_players", "1"); cvar_t cl_noblink = SCVAR("cl_noblink", "0"); cvar_t cl_servername = SCVAR("cl_servername", "none"); cvar_t qtvcl_forceversion1 = SCVAR("qtvcl_forceversion1", "0"); +cvar_t qtvcl_eztvextensions = SCVAR("qtvcl_eztvextensions", "0"); cvar_t cl_demospeed = FCVAR("cl_demospeed", "demo_setspeed", "1", 0); @@ -2456,7 +2457,7 @@ void CL_ReadPackets (void) continue; } - if (net_message.cursize < 6 && cls.demoplayback != DPB_MVD) //MVDs don't have the whole sequence header thing going on + if (net_message.cursize < 6 && (cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) //MVDs don't have the whole sequence header thing going on { Con_TPrintf (TL_RUNTPACKET,NET_AdrToString(net_from)); continue; @@ -2512,7 +2513,7 @@ void CL_ReadPackets (void) break; break; case CP_QUAKEWORLD: - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { MSG_BeginReading(); cls.netchan.last_received = realtime; @@ -2547,7 +2548,7 @@ void CL_ReadPackets (void) return; } - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) MVD_Interpolate(); } @@ -2905,6 +2906,7 @@ void CL_Init (void) Cvar_Register (&ruleset_allow_larger_models, cl_controlgroup); Cvar_Register (&qtvcl_forceversion1, cl_controlgroup); + Cvar_Register (&qtvcl_eztvextensions, cl_controlgroup); #ifdef WEBCLIENT Cmd_AddCommand ("ftp", CL_FTP_f); #endif diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 9085e0eb1..ad0971e8d 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -872,10 +872,19 @@ void Sound_NextDownload (void) else #endif { - if (CL_RemoveClientCommands("modellist")) - Con_Printf("Multiple modellists\n"); -// CL_SendClientCommand ("modellist %i 0", cl.servercount); - CL_SendClientCommand (true, modellist_name, cl.servercount, 0); + if (cls.demoplayback == DPB_EZTV) + { + if (CL_RemoveClientCommands("qtvmodellist")) + Con_Printf("Multiple modellists\n"); + CL_SendClientCommand (true, "qtvmodellist %i 0", cl.servercount); + } + else + { + if (CL_RemoveClientCommands("modellist")) + Con_Printf("Multiple modellists\n"); +// CL_SendClientCommand ("modellist %i 0", cl.servercount); + CL_SendClientCommand (true, modellist_name, cl.servercount, 0); + } } } @@ -910,6 +919,11 @@ void CL_RequestNextDownload (void) return; //not yet cl.sendprespawn = false; +#ifdef _MSC_VER + //FIXME: timedemo timer should start here. +#else +#warning timedemo timer should start here +#endif #ifdef Q2CLIENT @@ -926,11 +940,21 @@ void CL_RequestNextDownload (void) Con_Printf("\n\n-------------\nCouldn't download %s - cannot fully connect\n", cl.worldmodel->name); return; } + + if (cls.demoplayback == DPB_EZTV) + { + if (CL_RemoveClientCommands("qtvspawn")) + Con_Printf("Multiple prespawns\n"); + CL_SendClientCommand(true, "qtvspawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2); + } + else + { // done with modellist, request first of static signon messages - if (CL_RemoveClientCommands("prespawn")) - Con_Printf("Multiple prespawns\n"); - // CL_SendClientCommand("prespawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2); - CL_SendClientCommand(true, prespawn_name, cl.servercount, LittleLong(cl.worldmodel->checksum2)); + if (CL_RemoveClientCommands("prespawn")) + Con_Printf("Multiple prespawns\n"); + // CL_SendClientCommand("prespawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2); + CL_SendClientCommand(true, prespawn_name, cl.servercount, LittleLong(cl.worldmodel->checksum2)); + } } } @@ -1679,7 +1703,7 @@ void CL_ParseServerData (void) T_FreeStrings(); } - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { int i; extern float nextdemotime; @@ -1762,11 +1786,20 @@ void CL_ParseServerData (void) else #endif { - if (CL_RemoveClientCommands("soundlist")) - Con_Printf("Multiple soundlists\n"); - // ask for the sound list next -// CL_SendClientCommand ("soundlist %i 0", cl.servercount); - CL_SendClientCommand (true, soundlist_name, cl.servercount, 0); + if (cls.demoplayback == DPB_EZTV) + { + if (CL_RemoveClientCommands("qtvsoundlist")) + Con_Printf("Multiple soundlists\n"); + CL_SendClientCommand (true, "qtvsoundlist %i 0", cl.servercount); + } + else + { + if (CL_RemoveClientCommands("soundlist")) + Con_Printf("Multiple soundlists\n"); + // ask for the sound list next +// CL_SendClientCommand ("soundlist %i 0", cl.servercount); + CL_SendClientCommand (true, soundlist_name, cl.servercount, 0); + } } // now waiting for downloads, etc @@ -2273,10 +2306,13 @@ void CL_ParseSoundlist (void) if (n) { - if (CL_RemoveClientCommands("soundlist")) - Con_Printf("Multiple soundlists\n"); -// CL_SendClientCommand("soundlist %i %i", cl.servercount, n); - CL_SendClientCommand(true, soundlist_name, cl.servercount, n); + if (cls.demoplayback != DPB_EZTV) + { + if (CL_RemoveClientCommands("soundlist")) + Con_Printf("Multiple soundlists\n"); +// CL_SendClientCommand("soundlist %i %i", cl.servercount, n); + CL_SendClientCommand(true, soundlist_name, cl.servercount, n); + } return; } @@ -2344,10 +2380,13 @@ void CL_ParseModellist (qboolean lots) if (n) { - if (CL_RemoveClientCommands("modellist")) - Con_Printf("Multiple modellists\n"); -// CL_SendClientCommand("modellist %i %i", cl.servercount, n); - CL_SendClientCommand(true, modellist_name, cl.servercount, (nummodels&0xff00) + n); + if (cls.demoplayback != DPB_EZTV) + { + if (CL_RemoveClientCommands("modellist")) + Con_Printf("Multiple modellists\n"); +// CL_SendClientCommand("modellist %i %i", cl.servercount, n); + CL_SendClientCommand(true, modellist_name, cl.servercount, (nummodels&0xff00) + n); + } return; } @@ -2885,13 +2924,13 @@ void CL_ParseClientdata (void) oldparsecountmod = parsecountmod; i = cls.netchan.incoming_acknowledged; - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) cl.oldparsecount = i - 1; cl.parsecount = i; i &= UPDATE_MASK; parsecountmod = i; frame = &cl.frames[i]; - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) frame->senttime = realtime - host_frametime; parsecounttime = cl.frames[i].senttime; @@ -3110,21 +3149,9 @@ void CL_ServerInfo (void) CL_SetStat ===================== */ -void CL_SetStat (int pnum, int stat, int value) +static void CL_SetStat_Internal (int pnum, int stat, int value) { int j; - if (stat < 0 || stat >= MAX_CL_STATS) - return; -// Host_EndGame ("CL_SetStat: %i is invalid", stat); - - if (cls.demoplayback == DPB_MVD) - { - extern int cls_lastto; - cl.players[cls_lastto].stats[stat]=value; - if ( spec_track[pnum] != cls_lastto ) - return; - } - if (cl.stats[pnum][stat] != value) Sbar_Changed (); @@ -3138,15 +3165,6 @@ void CL_SetStat (int pnum, int stat, int value) if (stat == STAT_VIEWHEIGHT && cls.z_ext & Z_EXT_VIEWHEIGHT) cl.viewheight[pnum] = value; - if (stat == STAT_TIME && (cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) - { - cl.oldgametime = cl.gametime; - cl.oldgametimemark = cl.gametimemark; - - cl.gametime = value * 0.001; - cl.gametimemark = realtime; - } - if (stat == STAT_WEAPON) { if (cl.stats[pnum][stat] != value) @@ -3164,6 +3182,34 @@ void CL_SetStat (int pnum, int stat, int value) TP_StatChanged(stat, value); } +void CL_SetStat (int pnum, int stat, int value) +{ + if (stat < 0 || stat >= MAX_CL_STATS) + return; +// Host_EndGame ("CL_SetStat: %i is invalid", stat); + + if (stat == STAT_TIME && (cls.fteprotocolextensions & PEXT_ACCURATETIMINGS)) + { + cl.oldgametime = cl.gametime; + cl.oldgametimemark = cl.gametimemark; + + cl.gametime = value * 0.001; + cl.gametimemark = realtime; + } + + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) + { + extern int cls_lastto; + cl.players[cls_lastto].stats[stat]=value; + + for (pnum = 0; pnum < cl.splitclients; pnum++) + if (spec_track[pnum] == cls_lastto) + CL_SetStat_Internal(pnum, stat, value); + } + else + CL_SetStat_Internal(pnum, stat, value); +} + /* ============== CL_MuzzleFlash @@ -4073,7 +4119,9 @@ void CL_ParseServerMessage (void) break; case svc_disconnect: - if (cls.state == ca_connected) + if (cls.demoplayback == DPB_EZTV) //eztv fails to detect the end of demos. + MSG_ReadString(); + else if (cls.state == ca_connected) { Host_EndGame ("Server disconnected\n" "Server version may not be compatible"); @@ -4144,7 +4192,7 @@ void CL_ParseServerMessage (void) break; #endif case svc_setangle: - if (cls.demoplayback == DPB_MVD) + if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { i = MSG_ReadByte(); if (i != spec_track[0] || !autocam[0]) diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 8614095c3..85ed22249 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -379,6 +379,14 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user VectorCopy (u->angles, pmove.angles); VectorCopy (from->velocity, pmove.velocity); + if (!(pmove.velocity[0] == 0) && !(pmove.velocity[0] != 0)) + { + Con_Printf("nan velocity!\n"); + pmove.velocity[0] = 0; + pmove.velocity[1] = 0; + pmove.velocity[2] = 0; + } + pmove.jump_msec = (cls.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec; pmove.jump_held = from->jump_held; pmove.waterjumptime = from->waterjumptime; @@ -536,7 +544,7 @@ static void CL_LerpMove (int pnum, float msgtime) int i; int from, to; - if (cl_nolerp.value || cls.demoplayback == DPB_MVD) + if (cl_nolerp.value || cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV || cls.demoplayback == DPB_NETQUAKE) return; if (cls.netchan.outgoing_sequence < lastsequence) { @@ -642,7 +650,7 @@ void CL_CalcClientTime(void) cl.servertime = cl.oldgametime; } - if (cls.protocol == CP_NETQUAKE || (cls.demoplayback && cls.demoplayback != DPB_MVD)) + if (cls.protocol == CP_NETQUAKE || (cls.demoplayback && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) { float want; // float off; @@ -706,7 +714,7 @@ void CL_PredictMovePNum (int pnum) if (cl_pushlatency.value > 0) Cvar_Set (&cl_pushlatency, "0"); - if (cl.paused && !cls.demoplayback!=DPB_MVD && (!cl.spectator || !autocam[pnum])) + if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !autocam[pnum])) return; CL_CalcClientTime(); @@ -717,6 +725,11 @@ void CL_PredictMovePNum (int pnum) return; } + if (cls.demoplayback == DPB_NETQUAKE) + { + cl.ackedinputsequence = cls.netchan.outgoing_sequence; + } + if (!cl.ackedinputsequence) { return; @@ -787,7 +800,7 @@ void CL_PredictMovePNum (int pnum) } */ } #endif - if (((cl_nopred.value && cls.demoplayback!=DPB_MVD)|| cl.fixangle)) + if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| cl.fixangle)) { fixedorg: VectorCopy (vel, cl.simvel[pnum]); @@ -807,7 +820,7 @@ fixedorg: to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK]; - if (Cam_TrackNum(pnum)>=0 && !cl_nolerp.value && cls.demoplayback != DPB_MVD) + if (Cam_TrackNum(pnum)>=0 && !cl_nolerp.value && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV && cls.demoplayback != DPB_NETQUAKE) { float f; diff --git a/engine/client/client.h b/engine/client/client.h index 051a42922..ba97c7fe9 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -343,7 +343,7 @@ typedef struct // demo recording info must be here, because record is started before // entering a map (and clearing client_state_t) qboolean demorecording; - enum{DPB_NONE,DPB_QUAKEWORLD,DPB_MVD, + enum{DPB_NONE,DPB_QUAKEWORLD,DPB_MVD,DPB_EZTV, #ifdef NQPROT DPB_NETQUAKE, #endif diff --git a/engine/client/keys.c b/engine/client/keys.c index 0dc818998..52044c9b2 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -1603,7 +1603,7 @@ void Key_Event (int key, qboolean down) // during demo playback, most keys bring up the main menu // - if (cls.demoplayback && cls.demoplayback != DPB_MVD && down && consolekeys[key] && key != K_TAB && key_dest == key_game) + if (cls.demoplayback && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV && down && consolekeys[key] && key != K_TAB && key_dest == key_game) { M_ToggleMenu_f (); return;