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;