qtv changes allow you to spectate annother spectator. FTE changes fix independant physics stuff a bit, and fix AVI recording a little also.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2440 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2006-11-03 15:53:04 +00:00
parent b444ca99ac
commit acf93f1548
24 changed files with 537 additions and 220 deletions

View File

@ -452,40 +452,88 @@ readnext:
CL_StopPlayback ();
return 0;
}
// Con_Printf("demo packet %x\n", (int)c);
switch (c&7)
{
case dem_cmd :
// user sent input
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
pcmd = &cl.frames[i].cmd[0];
r = readdemobytes (&q1cmd, sizeof(q1cmd));
if (r != sizeof(q1cmd))
/* if (cls.demoplayback == DPB_MVD)
{
CL_StopPlayback ();
unsigned short samps;
unsigned char bits;
unsigned char rateid;
unsigned char audio[8192];
if (readdemobytes (&samps, 2) == 2)
{
if (readdemobytes (&bits, 1) == 1)
{
if (samps > sizeof(audio))
{
Con_Printf("Corrupted/too large audio chunk\n");
CL_StopPlayback();
return 0;
}
if (readdemobytes (&rateid, 1) == 1)
{
if (readdemobytes (audio, samps) == samps)
{
FILE *f;
samps = samps/(bits/8);
f = fopen("c:/test.raw", "r+b");
if (f)
{
fseek(f, 0, SEEK_END);
fwrite(audio, samps, bits/8, f);
fclose(f);
}
S_RawAudio(0, audio, 11025, samps, 1, bits/8);
break;
}
unreadbytes(1, &rateid);
}
unreadbytes(1, &bits);
}
unreadbytes(1, &samps);
}
unreadbytes(1, &c);
r = 0;
unreadbytes(1, &r);
return 0;
}
// byte order stuff
for (j = 0; j < 3; j++)
{
q1cmd.angles[j] = LittleFloat(q1cmd.angles[j]);
pcmd->angles[j] = ((int)(q1cmd.angles[j]*65536.0/360)&65535);
}
pcmd->forwardmove = q1cmd.forwardmove = LittleShort(q1cmd.forwardmove);
pcmd->sidemove = q1cmd.sidemove = LittleShort(q1cmd.sidemove);
pcmd->upmove = q1cmd.upmove = LittleShort(q1cmd.upmove);
pcmd->msec = q1cmd.msec;
pcmd->buttons = q1cmd.buttons;
else
{*/
// user sent input
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
pcmd = &cl.frames[i].cmd[0];
r = readdemobytes (&q1cmd, sizeof(q1cmd));
if (r != sizeof(q1cmd))
{
CL_StopPlayback ();
return 0;
}
// byte order stuff
for (j = 0; j < 3; j++)
{
q1cmd.angles[j] = LittleFloat(q1cmd.angles[j]);
pcmd->angles[j] = ((int)(q1cmd.angles[j]*65536.0/360)&65535);
}
pcmd->forwardmove = q1cmd.forwardmove = LittleShort(q1cmd.forwardmove);
pcmd->sidemove = q1cmd.sidemove = LittleShort(q1cmd.sidemove);
pcmd->upmove = q1cmd.upmove = LittleShort(q1cmd.upmove);
pcmd->msec = q1cmd.msec;
pcmd->buttons = q1cmd.buttons;
cl.frames[i].senttime = demotime;
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
cls.netchan.outgoing_sequence++;
for (i=0 ; i<3 ; i++)
{
readdemobytes (&f, 4);
cl.viewangles[0][i] = LittleFloat (f);
}
cl.frames[i].senttime = demotime;
cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
cls.netchan.outgoing_sequence++;
for (i=0 ; i<3 ; i++)
{
readdemobytes (&f, 4);
cl.viewangles[0][i] = LittleFloat (f);
}
/* }*/
break;
case dem_read:
@ -1384,6 +1432,7 @@ void CL_PlayDemo(char *demoname)
void CL_QTVPlay (vfsfile_t *newf)
{
#define BUFFERTIME 10
CL_Disconnect_f ();
cls.demofile = newf;
@ -1396,11 +1445,11 @@ void CL_QTVPlay (vfsfile_t *newf)
cls.state = ca_demostart;
net_message.packing = SZ_RAWBYTES;
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
realtime = -10;
cl.gametime = -10;
realtime = -BUFFERTIME;
cl.gametime = -BUFFERTIME;
cl.gametimemark = realtime;
Con_Printf("Buffering for ten seconds\n");
Con_Printf("Buffering for %i seconds\n", (int)-realtime);
cls.netchan.last_received=realtime;
@ -1416,7 +1465,8 @@ void CL_QTVPoll (void)
{
char *s, *e, *colon;
int len;
qboolean error = false;
qboolean streamavailable = false;
qboolean saidheader = false;
if (!qtvrequest)
return;
@ -1451,23 +1501,37 @@ void CL_QTVPoll (void)
{
*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);
error = true;
}
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);
error = true; //not really an error, but meh
}
else if (!strcmp(s, "ASOURCE"))
{ //printable error
Con_Printf("Source%s is available\n", colon);
error = true;
{ //printable source
if (!saidheader)
{
saidheader=true;
Con_Printf("Available Sources:\n");
}
Con_Printf("%s\n", colon);
}
else if (!strcmp(s, "BEGIN"))
streamavailable = true;
}
else
{
if (!strcmp(s, "BEGIN"))
streamavailable = true;
}
//from e to s, we have a line
s = e+1;
@ -1475,7 +1539,7 @@ void CL_QTVPoll (void)
e++;
}
if (!error)
if (streamavailable)
{
CL_QTVPlay(qtvrequest);
qtvrequest = NULL;
@ -1488,6 +1552,16 @@ void CL_QTVPoll (void)
qtvrequestsize = 0;
}
char *strchrrev(char *str, char chr)
{
char *firstchar = str;
for (str = str + strlen(str)-1; str>=firstchar; str--)
if (*str == chr)
return str;
return NULL;
}
void CL_QTVPlay_f (void)
{
qboolean raw=0;
@ -1495,6 +1569,12 @@ void CL_QTVPlay_f (void)
vfsfile_t *newf;
char *host;
if (Cmd_Argc() < 2)
{
Con_Printf("Usage: qtvplay [stream@]hostname[:port] [password]\n");
return;
}
connrequest = Cmd_Argv(1);
if (*connrequest == '#')
@ -1530,7 +1610,7 @@ void CL_QTVPlay_f (void)
host = connrequest;
connrequest = strchr(connrequest, '@');
connrequest = strchrrev(connrequest, '@');
if (connrequest)
host = connrequest+1;
newf = FS_OpenTCP(host);
@ -1541,8 +1621,7 @@ void CL_QTVPlay_f (void)
return;
}
host = connrequest = Cmd_Argv(1);
connrequest = strchr(connrequest, '@');
host = Cmd_Argv(1);
if (connrequest)
*connrequest = '\0';
else
@ -1582,53 +1661,6 @@ void CL_QTVPlay_f (void)
}
}
/*
void CL_QTVPlay_f (void)
{
char *connrequest;
vfsfile_t *newf;
newf = FS_OpenTCP(Cmd_Argv(1));
if (!newf)
{
Con_Printf("Couldn't connect to proxy\n");
return;
}
connrequest = "QTV\n"
"VERSION: 1\n"
"RAW: 1\n";
VFS_WRITE(newf, connrequest, strlen(connrequest));
connrequest = "SOURCE: file:test.mvd\n";
VFS_WRITE(newf, connrequest, strlen(connrequest));
connrequest = "\n";
VFS_WRITE(newf, connrequest, strlen(connrequest));
CL_Disconnect_f ();
cls.demofile = newf;
unreadcount = 0; //just in case
cls.demoplayback = DPB_MVD;
cls.findtrack = true;
cls.state = ca_demostart;
net_message.packing = SZ_RAWBYTES;
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
realtime = -10;
cl.gametime = -10;
cl.gametimemark = realtime;
Con_Printf("Buffering for ten seconds\n");
cls.netchan.last_received=realtime;
cls.protocol = CP_QUAKEWORLD;
TP_ExecTrigger ("f_demostart");
}
*/
void CL_QTVList_f (void)
{
char *connrequest;
@ -1653,30 +1685,6 @@ void CL_QTVList_f (void)
VFS_CLOSE(qtvrequest);
qtvrequest = newf;
qtvrequestsize = 0;
/*
CL_Disconnect_f ();
cls.demofile = newf;
unreadcount = 0; //just in case
cls.demoplayback = DPB_MVD;
cls.findtrack = true;
cls.state = ca_demostart;
net_message.packing = SZ_RAWBYTES;
Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, 0);
realtime = 0;
cl.gametime = 0;
cl.gametimemark = realtime;
Con_Printf("Querying proxy\n");
cls.netchan.last_received=realtime;
cls.protocol = CP_QUAKEWORLD;
TP_ExecTrigger ("f_demostart");*/
}
/*

View File

@ -2898,7 +2898,7 @@ void CL_LinkPlayers (void)
ent->origin[0] = cl.simorg[pnum][0];
ent->origin[1] = cl.simorg[pnum][1];
ent->origin[2] = cl.simorg[pnum][2]+cl.crouch[pnum];
ent->flags |= 2;
ent->flags |= Q2RF_EXTERNALMODEL;
break;
}
}

View File

@ -843,7 +843,7 @@ float CL_FilterTime (double time, float wantfps) //now returns the extra time no
if (wantfps < 1)
fps = fpscap;
else
fps = bound (10.0, wantfps, fpscap);
fps = bound (6.7, wantfps, fpscap); //we actually cap ourselves to 150msecs (1000/7 = 142)
}
if (time < 1000 / fps)
@ -983,15 +983,21 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param)
int sleeptime;
float fps;
float time, lasttime;
float spare;
lasttime = Sys_DoubleTime();
while(1)
{
EnterCriticalSection(&indepcriticialsection);
time = Sys_DoubleTime();
if (cls.state)
CL_SendCmd(time - lasttime);
lasttime = time;
LeaveCriticalSection(&indepcriticialsection);
spare = CL_FilterTime((time - lasttime)*1000, cl_netfps.value);
if (spare)
{
time -= spare/1000.0f;
EnterCriticalSection(&indepcriticialsection);
if (cls.state)
CL_SendCmd(time - lasttime);
lasttime = time;
LeaveCriticalSection(&indepcriticialsection);
}
fps = cl_netfps.value;
if (fps < 4)
@ -1003,6 +1009,8 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param)
if (sleeptime)
Sleep(sleeptime);
else
Sleep(1);
}
}
@ -1014,11 +1022,18 @@ void CL_UseIndepPhysics(qboolean allow)
if (allow)
{ //enable it
DWORD tid; //*sigh*...
// TIMECAPS tc;
// timeGetDevCaps(&tc, sizeof(TIMECAPS));
// Con_Printf("Timer has a resolution of %i millisecond%s\n", tc.wPeriodMin, tc.wPeriodMin!=1?"s":"");
InitializeCriticalSection(&indepcriticialsection);
runningindepphys = true;
indepphysicsthread = CreateThread(NULL, 8192, CL_IndepPhysicsThread, NULL, 0, &tid);
allowindepphys = 1;
SetThreadPriority(independantphysics, HIGH_PRIORITY_CLASS);
}
else
{
@ -1050,6 +1065,7 @@ CL_SendCmd
vec3_t accum[MAX_SPLITS];
void CL_SendCmd (float frametime)
{
extern cvar_t cl_indepphysics;
sizebuf_t buf;
qbyte data[512];
int i, plnum;
@ -1185,10 +1201,17 @@ void CL_SendCmd (float frametime)
independantphysics[plnum].msec = msecstouse;
}
// if (!CL_FilterTime(msecstouse, cl_netfps.value<=0?cl_maxfps.value:cl_netfps.value) && msecstouse<255 && cls.state == ca_active)
// {
// return;
// }
if (cl_netfps.value && !cl_indepphysics.value)
{
int spare;
spare = CL_FilterTime(msecstouse, cl_netfps.value<=0?cl_maxfps.value:cl_netfps.value);
if (!spare && msecstouse<255 && cls.state == ca_active)
{
return;
}
if (spare > 0)
msecstouse -= spare;
}
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE)

View File

@ -27,10 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cl_master.h"
#include "cl_ignore.h"
#if defined(_WIN32) && !defined(MINGW) && defined(RGLQUAKE)
//#define WINAVI
#endif
// callbacks
void CL_Sbar_Callback(struct cvar_s *var, char *oldvalue);
void Name_Callback(struct cvar_s *var, char *oldvalue);
@ -1029,6 +1025,7 @@ void CL_Disconnect (void)
qbyte final[12];
connect_time = -1;
connect_tries = 0;
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE);
@ -3038,11 +3035,6 @@ Host_Frame
Runs all active servers
==================
*/
#if defined(WINAVI) && !defined(NOMEDIA)
extern float recordavi_frametime;
qboolean Media_Capturing();
#endif
extern cvar_t cl_netfps;
int nopacketcount;
void SNDDMA_SetUnderWater(qboolean underwater);
@ -3054,7 +3046,7 @@ void Host_Frame (double time)
static double time3 = 0;
int pass1, pass2, pass3;
// float fps;
float realframetime;
double realframetime;
static double spare;
RSpeedLocals();
@ -3062,14 +3054,7 @@ void Host_Frame (double time)
if (setjmp (host_abort) )
return; // something bad happened, or the server disconnected
realframetime = time;
#if defined(WINAVI) && !defined(NOMEDIA)
if (cls.demoplayback && Media_Capturing() && recordavi_frametime>0.01)
{
realframetime = time = recordavi_frametime;
}
#endif
realframetime = time = Media_TweekCaptureFrameTime(time);
// if (cls.demoplayback && cl_demospeed.value>0)
// realframetime *= cl_demospeed.value; // this probably screws up other timings
@ -3117,10 +3102,11 @@ void Host_Frame (double time)
*/
Mod_Think(); //think even on idle (which means small walls and a fast cpu can get more surfaces done.
if (cl_maxfps.value>0 && (cl_netfps.value>0 || cls.demoplayback))
if ((cl_netfps.value>0 || cls.demoplayback || cl_indepphysics.value))
{ //limit the fps freely, and expect the netfps to cope.
if ((realtime - oldrealtime) < 1/cl_maxfps.value)
return;
if (cl_maxfps.value > 0)
if ((realtime - oldrealtime) < 1/cl_maxfps.value)
return;
}
else
{

View File

@ -3716,8 +3716,19 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
Cmd_ExecuteString(stufftext, RESTRICT_SERVER+destsplit); //do this NOW so that it's done before any models or anything are loaded
else
{
if (!strncmp(stufftext, "//querycmd ", 11))
{
COM_Parse(stufftext + 11);
if (Cmd_Exists(com_token))
{
Cbuf_AddText ("cmd cmdsupported ", RESTRICT_SERVER+destsplit);
Cbuf_AddText (com_token, RESTRICT_SERVER+destsplit);
Cbuf_AddText ("\n", RESTRICT_SERVER+destsplit);
}
}
else
#ifdef CSQC_DAT
if (!CSQC_StuffCmd(stufftext))
if (!CSQC_StuffCmd(stufftext))
#endif
{
Cbuf_AddText (stufftext, RESTRICT_SERVER+destsplit);

View File

@ -767,7 +767,7 @@ char *Media_NextTrack(void)
//Avi files are specific to windows. Bit of a bummer really.
#if defined(_WIN32) && !defined(__GNUC__)
//#define WINAVI
#define WINAVI
#endif
@ -1462,7 +1462,7 @@ unsigned long recordavi_codec_fourcc;
soundcardinfo_t *capture_fakesounddevice;
int recordavi_video_frame_counter;
int recordavi_audio_frame_counter;
float recordavi_frametime;
float recordavi_frametime; //length of a frame in fractional seconds
float recordavi_videotime;
float recordavi_audiotime;
int capturesize;
@ -1512,6 +1512,16 @@ qboolean Media_PausedDemo (void)
return false;
}
double Media_TweekCaptureFrameTime(double time)
{
if (cls.demoplayback && Media_Capturing() && recordavi_frametime>0.01)
{
return time = recordavi_frametime;
}
return time;
}
void Media_RecordFrame (void)
{
if (!capturetype)
@ -1546,19 +1556,12 @@ void Media_RecordFrame (void)
}
//time for annother frame?
/*if (recordavi_uncompressed_audio_stream) //sync video to the same frame as audio.
{
if (recordavi_video_frame_counter > recordavi_audio_frame_counter)
goto skipframe;
}
else*/
{
if (recordavi_videotime > realtime+1)
recordavi_videotime = realtime; //urm, wrapped?..
if (recordavi_videotime > realtime)
goto skipframe;
recordavi_videotime += recordavi_frametime;
}
if (recordavi_videotime > realtime+1)
recordavi_videotime = realtime; //urm, wrapped?..
if (recordavi_videotime > realtime)
goto skipframe;
recordavi_videotime += recordavi_frametime;
//audio is mixed to match the video times
switch (capturetype)
{
@ -1796,7 +1799,7 @@ void Media_RecordFilm_f (void)
!strcmp(fourcc, "pcx"))
{
capturetype = CT_SCREENSHOT;
strcpy(capturefilenameprefix, Cmd_Argv(1));
Q_strncpyz(capturefilenameprefix, Cmd_Argv(1), sizeof(capturefilenameprefix));
}
else
{
@ -1836,7 +1839,7 @@ void Media_RecordFilm_f (void)
}
snprintf(filename, 192, "%s%s", com_quakedir, Cmd_Argv(1));
snprintf(filename, sizeof(filename) - 5, "%s%s", com_quakedir, Cmd_Argv(1));
COM_StripExtension(filename, filename, sizeof(filename));
COM_DefaultExtension (filename, ".avi", sizeof(filename));
@ -1952,6 +1955,7 @@ void Media_RecordFilm_f (void)
else
{
Con_Printf("That sort of video capturing is not supported in this build\n");
capturetype = CT_NONE;
}
}
void Media_CaptureDemoEnd(void)
@ -1968,6 +1972,8 @@ void Media_RecordDemo_f(void)
if (capturetype != CT_NONE)
recordingdemo = true;
else
CL_Stopdemo_f(); //capturing failed for some reason
}
#else
void Media_CaptureDemoEnd(void){}

View File

@ -15,10 +15,12 @@ qboolean M_Script_Key (int key, menu_t *menu)
{
if (menu->selecteditem && menu->selecteditem->common.type == mt_edit)
return false;
if (key >= '0' && key <= '9')
if (key >= '0' && key <= '9' && *menualias.string)
{
if (key == '0') //specal case so that "hello" < "0"... (plus matches impulses)
Cbuf_AddText(va("set option %i\n%s\n", key-'0'+1, menualias.string), RESTRICT_LOCAL);
if (key == '0') //specal case so that "hello" < "0"... (plus matches common impulses)
Cbuf_AddText(va("set option %i\n%s\n", 10, menualias.string), RESTRICT_LOCAL);
else
Cbuf_AddText(va("set option %i\n%s\n", key-'0', menualias.string), RESTRICT_LOCAL);
return true;
}
return false;
@ -150,7 +152,10 @@ void M_MenuS_Picture_f (void)
return;
}
MC_AddPicture(menu_script, x, y, picname);
if (!strcmp(Cmd_Argv(1), "-"))
MC_AddCenterPicture(menu_script, y, picname);
else
MC_AddPicture(menu_script, x, y, picname);
}
void M_MenuS_Edit_f (void)

View File

@ -311,6 +311,7 @@ qboolean Media_ShowFilm(void);
void Media_CaptureDemoEnd(void);
void Media_RecordFrame (void);
qboolean Media_PausedDemo (void);
double Media_TweekCaptureFrameTime(double time);
void R_SetRenderer(int wanted);
void RQ_Init(void);

View File

@ -1732,7 +1732,14 @@ void Sbar_Draw (void)
if (scr_viewsize.value != 120)
Cvar_Set(&scr_viewsize, "120");
Sbar_DrawString (0, -8, va("%i", cl.stats[pnum][STAT_HEALTH]));
Sbar_DrawString (0, -8, va("Health: %i", cl.stats[pnum][STAT_HEALTH]));
Sbar_DrawString (0, -16, va(" Armor: %i", cl.stats[pnum][STAT_ARMOR]));
if (cl.stats[pnum][STAT_H2_BLUEMANA])
Sbar_DrawString (0, -24, va(" Blue: %i", cl.stats[pnum][STAT_H2_BLUEMANA]));
if (cl.stats[pnum][STAT_H2_GREENMANA])
Sbar_DrawString (0, -32, va(" Green: %i", cl.stats[pnum][STAT_H2_GREENMANA]));
continue;
}

View File

@ -1640,10 +1640,24 @@ void Cmd_ForwardToServer_f (void)
return;
}
if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0) {
if (Q_strcasecmp(Cmd_Argv(1), "snap") == 0)
{
if (SCR_RSShot())
return;
}
if (Q_strcasecmp(Cmd_Argv(1), "ptrack") == 0)
{
if (!*Cmd_Argv(2))
{
Cam_Unlock(0);
}
else
{
Cam_Lock(0, atoi(Cmd_Argv(2)));
autocam[0] = CAM_TRACK;
}
return;
}
if (cls.demoplayback)
return; // not really connected

View File

@ -618,6 +618,7 @@ qboolean CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surf
static mplane_t mainplane, patchplanes[20];
qboolean skip[20];
int numpatchplanes = 0;
float dot;
int matchplane;
@ -709,10 +710,14 @@ qboolean CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surf
for (matchplane = 0; matchplane < numplanes; matchplane++)
{
if (!memcmp(&map_planes[matchplane], &patchplanes[i], sizeof(patchplanes[i])))
if (map_planes[matchplane].dist+0.1 > patchplanes[i].dist && map_planes[matchplane].dist-0.1 < patchplanes[i].dist)
{
plane = &map_planes[matchplane];
break;
dot = DotProduct(map_planes[matchplane].normal, patchplanes[i].normal);
if (dot >= 0.98)
{
plane = &map_planes[matchplane];
break;
}
}
}
if (matchplane == numplanes)

View File

@ -400,6 +400,28 @@ char *COM_TrimString(char *str)
return buffer;
}
#ifdef _WIN32
#if (_MSC_VER >= 1400)
//with MSVC 8, use MS extensions
#define snprintf linuxlike_snprintf_vc8
int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...);
#define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
#else
//msvc crap
#define snprintf linuxlike_snprintf
int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...);
#define vsnprintf linuxlike_vsnprintf
int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
#endif
#ifdef _MSC_VER
//these are provided so we don't use them
//but mingw has some defines elsewhere and makes gcc moan
#define _vsnprintf unsafe_vsnprintf
#define _snprintf unsafe_snprintf
#endif
#endif
char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
{
static char buf[256];
@ -509,7 +531,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
if (!func)
{
assignment[-1] = '=';
sprintf(buf, "Can't find function %s\n", s);
snprintf(buf, sizeof(buf), "Can't find function %s\n", s);
return buf;
}
*(func_t *)val = (func - pr_progstate[i].functions) | (i<<24);

View File

@ -384,8 +384,8 @@ void QC_AddSharedFieldVar(progfuncs_t *progfuncs, int num, char *stringtable)
}
//oh well, must be a parameter.
if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
return;
case 32:
for (i=1 ; i<pr_progs->numfielddefs; i++)

View File

@ -1183,7 +1183,7 @@ void SV_MVDPings (void);
void SV_MVDWriteToDisk(int type, int to, float time);
void MVDWrite_Begin(qbyte type, int to, int size);
void MVDSetMsgBuf(demobuf_t *prev,demobuf_t *cur);
void SV_MVDStop (int reason);
void SV_MVDStop (int reason, qboolean mvdonly);
void SV_MVDStop_f (void);
void SV_MVDWritePackets (int num);
void MVD_Init (void);

View File

@ -1295,6 +1295,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
}
}
}
SV_MVD_SendInitialGamestate(NULL);
}
#endif

View File

@ -112,7 +112,7 @@ void DestFlush(qboolean compleate)
if (!demo.dest)
{
SV_MVDStop(2);
SV_MVDStop(2, false);
return;
}
}
@ -497,6 +497,7 @@ void SV_MVD_RunPendingConnections(void)
if (p->hasauthed == true)
{
e = ("QTVSV 1\n"
"BEGIN\n"
"\n");
send(p->socket, e, strlen(e), 0);
e = NULL;
@ -531,18 +532,29 @@ void SV_MVD_RunPendingConnections(void)
}
}
void DestCloseAllFlush(qboolean destroyfiles)
int DestCloseAllFlush(qboolean destroyfiles, qboolean mvdonly)
{
mvddest_t *d;
int numclosed = 0;
mvddest_t *d, **prev;
DestFlush(true); //make sure it's all written.
while (demo.dest)
prev = &demo.dest;
d = demo.dest;
while(d)
{
d = demo.dest;
demo.dest = d->nextdest;
if (!mvdonly || d->desttype != DEST_STREAM)
{
*prev = d->nextdest;
DestClose(d, destroyfiles);
numclosed++;
}
else
prev = &d;
DestClose(d, destroyfiles);
d = (*prev)->nextdest;
}
return numclosed;
}
@ -1504,8 +1516,9 @@ SV_Stop
stop recording a demo
====================
*/
void SV_MVDStop (int reason)
void SV_MVDStop (int reason, qboolean mvdonly)
{
int numclosed;
if (!sv.mvdrecording)
{
Con_Printf ("Not recording a demo.\n");
@ -1514,7 +1527,7 @@ void SV_MVDStop (int reason)
if (reason == 2)
{
DestCloseAllFlush(true);
DestCloseAllFlush(true, mvdonly);
// stop and remove
if (!demo.dest)
@ -1539,14 +1552,17 @@ void SV_MVDStop (int reason)
SV_MVDWritePackets(demo.parsecount - demo.lastwritten + 1);
// finish up
DestCloseAllFlush(false);
numclosed = DestCloseAllFlush(false, mvdonly);
sv.mvdrecording = false;
if (!reason)
SV_BroadcastPrintf (PRINT_CHAT, "Server recording completed\n");
else
SV_BroadcastPrintf (PRINT_CHAT, "Server recording stoped\nMax demo size exceeded\n");
if (!demo.dest)
sv.mvdrecording = false;
if (numclosed)
{
if (!reason)
SV_BroadcastPrintf (PRINT_CHAT, "Server recording completed\n");
else
SV_BroadcastPrintf (PRINT_CHAT, "Server recording stoped\nMax demo size exceeded\n");
}
Cvar_ForceSet(Cvar_Get("serverdemo", "", CVAR_NOSET, ""), "");
}
@ -1558,7 +1574,7 @@ SV_Stop_f
*/
void SV_MVDStop_f (void)
{
SV_MVDStop(0);
SV_MVDStop(0, true);
}
/*
@ -1570,7 +1586,7 @@ Stops recording, and removes the demo
*/
void SV_MVD_Cancel_f (void)
{
SV_MVDStop(2);
SV_MVDStop(2, true);
}
/*
@ -1631,9 +1647,10 @@ void SV_WriteSetMVDMessage (void)
DestFlush(false);
}
void SV_MVD_SendInitialGamestate(mvddest_t *dest);
static qboolean SV_MVD_Record (mvddest_t *dest)
{
sizebuf_t buf;
/* sizebuf_t buf;
char buf_data[MAX_QWMSGLEN];
int n, i;
char *s, info[MAX_INFO_STRING];
@ -1641,6 +1658,8 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
client_t *player;
char *gamedir;
int seq = 1;
*/
int i;
if (!dest)
return false;
@ -1663,16 +1682,36 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
demo.datagram.maxsize = sizeof(demo.datagram_data);
demo.datagram.data = demo.datagram_data;
sv.mvdrecording = true;
}
// else
// SV_WriteRecordMVDMessage(&buf, dem_read);
demo.pingtime = demo.time = sv.time;
dest->nextdest = demo.dest;
demo.dest = dest;
SV_MVD_SendInitialGamestate(dest);
return true;
}
void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{
sizebuf_t buf;
char buf_data[MAX_QWMSGLEN];
int n, i;
char *s, info[MAX_INFO_STRING];
client_t *player;
char *gamedir;
int seq = 1;
if (!demo.dest)
return;
sv.mvdrecording = true;
demo.pingtime = demo.time = sv.time;
singledest = dest;
/*-------------------------------------------------*/
@ -1937,9 +1976,6 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
SV_WriteSetMVDMessage();
singledest = NULL;
// done
return true;
}
/*

View File

@ -273,7 +273,7 @@ void Net_SendConnectionMVD(sv_t *qtv, oproxy_t *prox)
prox->flushing = false;
BuildServerData(qtv, &msg, true, 0, true);
BuildServerData(qtv, &msg, 0, NULL);
Prox_SendMessage(qtv->cluster, prox, msg.data, msg.cursize, dem_read, (unsigned)-1);
msg.cursize = 0;

View File

@ -28,6 +28,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, netadr_t adr)
{
int ret;
Sys_Printf(cluster, "udp send size %i\n", length);
if (length > 1000)
Sys_Printf(cluster, "udp send size %i\n", length);
ret = sendto(sock, data, length, 0, (struct sockaddr *)adr, sizeof(struct sockaddr_in));
if (ret < 0)
{

View File

@ -649,10 +649,19 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
tv->players[num].current.angles[2] = nonnullcmd.angles[2];
}
else
{
tv->players[num].current.angles[0] = tv->proxyplayerangles[0]/360*65535;
tv->players[num].current.angles[1] = tv->proxyplayerangles[1]/360*65535;
tv->players[num].current.angles[2] = tv->proxyplayerangles[2]/360*65535;
{ //the only reason we'd not get a command is if it's us.
if (tv->controller)
{
tv->players[num].current.angles[0] = tv->controller->ucmds[2].angles[0];
tv->players[num].current.angles[1] = tv->controller->ucmds[2].angles[1];
tv->players[num].current.angles[2] = tv->controller->ucmds[2].angles[2];
}
else
{
tv->players[num].current.angles[0] = tv->proxyplayerangles[0]/360*65535;
tv->players[num].current.angles[1] = tv->proxyplayerangles[1]/360*65535;
tv->players[num].current.angles[2] = tv->proxyplayerangles[2]/360*65535;
}
}
for (i=0 ; i<3 ; i++)

View File

@ -412,10 +412,12 @@ typedef struct viewer_s {
unsigned int currentstats[MAX_STATS];
int trackplayer;
int thisplayer;
int userid;
packet_entities_t frame[ENTITY_FRAMES];
struct viewer_s *next;
struct viewer_s *commentator;
char name[32];
char userinfo[1024];
@ -615,6 +617,7 @@ struct cluster_s {
sv_t *servers;
int numservers;
int nextstreamid;
int nextuserid;
//options
int qwlistenportnum;
@ -835,7 +838,7 @@ void WriteData(netmsg_t *b, const char *data, int length);
void Multicast(sv_t *tv, char *buffer, int length, int to, unsigned int playermask,int suitablefor);
void Broadcast(cluster_t *cluster, char *buffer, int length, int suitablefor);
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask);
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag);
void BuildServerData(sv_t *tv, netmsg_t *msg, int servercount, viewer_t *spectatorflag);
void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount);
SOCKET QW_InitUDPSocket(int port);
void QW_UpdateUDPStuff(cluster_t *qtv);

View File

@ -477,6 +477,10 @@ SOURCE=.\parse.c
# End Source File
# Begin Source File
SOURCE=.\pmove.c
# End Source File
# Begin Source File
SOURCE=.\qw.c
!IF "$(CFG)" == "qtvprox - Win32 Release"

View File

@ -205,7 +205,7 @@ SOCKET QW_InitUDPSocket(int port)
return sock;
}
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag)
void BuildServerData(sv_t *tv, netmsg_t *msg, int servercount, viewer_t *viewer)
{
movevars_t movevars;
WriteByte(msg, svc_serverdata);
@ -217,10 +217,10 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
//dummy connection, for choosing a game to watch.
WriteString(msg, "qw");
if (mvd)
if (!viewer)
WriteFloat(msg, 0);
else
WriteByte(msg, (MAX_CLIENTS-1) | (spectatorflag?128:0));
WriteByte(msg, (MAX_CLIENTS-1) | (128));
WriteString(msg, "FTEQTV Proxy");
@ -249,10 +249,15 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
{
WriteString(msg, tv->gamedir);
if (mvd)
if (!viewer)
WriteFloat(msg, 0);
else
WriteByte(msg, tv->thisplayer | (spectatorflag?128:0));
{
if (tv->controller == viewer)
WriteByte(msg, viewer->thisplayer);
else
WriteByte(msg, viewer->thisplayer | 128);
}
WriteString(msg, tv->mapname);
@ -364,7 +369,7 @@ void SendServerData(sv_t *tv, viewer_t *viewer)
if (viewer->netchan.isnqprotocol)
BuildNQServerData(tv, &msg, false, viewer->thisplayer);
else
BuildServerData(tv, &msg, false, viewer->servercount, !tv || tv->controller != viewer);
BuildServerData(tv, &msg, viewer->servercount, viewer);
SendBufferToViewer(viewer, msg.data, msg.cursize, true);
@ -646,6 +651,7 @@ qboolean ChallengePasses(netadr_t *addr, int challenge)
void NewClient(cluster_t *cluster, viewer_t *viewer)
{
viewer->userid = ++cluster->nextuserid;
viewer->timeout = cluster->curtime + 15*1000;
viewer->trackplayer = -1;
@ -689,7 +695,7 @@ void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
strcpy(temp, "unnamed");
if (!*viewer->name)
Sys_Printf(cluster, "Viewer %s connected\n", temp);
Q_strncpyz(viewer->name, temp, sizeof(temp));
Q_strncpyz(viewer->name, temp, sizeof(viewer->name));
Info_ValueForKey(viewer->userinfo, "rate", temp, sizeof(temp));
rate = atof(temp);
@ -815,6 +821,7 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
memset(viewer, 0, sizeof(viewer_t));
Netchan_Setup (cluster->qwdsocket, &viewer->netchan, *addr, atoi(qport), false);
viewer->netchan.message.maxsize = 1400;
viewer->next = cluster->viewers;
cluster->viewers = viewer;
@ -1717,12 +1724,15 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
{
viewer_t *cv;
packet_entities_t *e;
int i;
usercmd_t to;
unsigned short flags;
short interp;
float lerp;
int track;
int runaway = 10;
memset(&to, 0, sizeof(to));
@ -1749,6 +1759,21 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
if (tv->controller == v)
lerp = 1;
track = v->trackplayer;
for (cv = v; cv && runaway-->0; cv = cv->commentator)
{
track = cv->trackplayer;
if (track != MAX_CLIENTS-2)
break;
}
/*
if (v->commentator && track == MAX_CLIENTS-2)
{
track = v->commentator->trackplayer;
if (track < 0)
track = MAX_CLIENTS-2;
}*/
for (i = 0; i < MAX_CLIENTS; i++)
{
if (i == v->thisplayer)
@ -1756,14 +1781,56 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
SendLocalPlayerState(tv, v, i, msg);
continue;
}
if (v->commentator)// && track == i)
{
if (i == MAX_CLIENTS-2)
{
flags = PF_COMMAND;
WriteByte(msg, svc_playerinfo);
WriteByte(msg, i);
WriteShort(msg, flags);
interp = v->commentator->origin[0]*8;
WriteShort(msg, interp);
interp = v->commentator->origin[1]*8;
WriteShort(msg, interp);
interp = v->commentator->origin[2]*8;
WriteShort(msg, interp);
WriteByte(msg, 0);
if (flags & PF_MSEC)
{
WriteByte(msg, 0);
}
if (flags & PF_COMMAND)
{
to.angles[0] = v->commentator->ucmds[2].angles[0];
to.angles[1] = v->commentator->ucmds[2].angles[1];
to.angles[2] = v->commentator->ucmds[2].angles[2];
WriteDeltaUsercmd(msg, &nullcmd, &to);
}
if (flags & PF_MODEL)
WriteByte(msg, tv->players[i].current.modelindex);
if (flags & PF_WEAPONFRAME)
WriteByte(msg, tv->players[i].current.weaponframe);
continue;
}
if (track == i)
continue;
}
if (!tv->players[i].active)
continue;
if (v->trackplayer != i && !BSP_Visible(tv->bsp, tv->players[i].leafcount, tv->players[i].leafs))
//bsp cull. currently tracked player is always visible
if (track != i && !BSP_Visible(tv->bsp, tv->players[i].leafcount, tv->players[i].leafs))
continue;
flags = PF_COMMAND;
if (v->trackplayer == i && tv->players[i].current.weaponframe)
if (track == i && tv->players[i].current.weaponframe)
flags |= PF_WEAPONFRAME;
WriteByte(msg, svc_playerinfo);
@ -1860,6 +1927,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
void UpdateStats(sv_t *qtv, viewer_t *v)
{
viewer_t *cv;
netmsg_t msg;
char buf[6];
int i;
@ -1869,12 +1937,17 @@ void UpdateStats(sv_t *qtv, viewer_t *v)
InitNetMsg(&msg, buf, sizeof(buf));
if (qtv && qtv->controller == v)
if (v->commentator)
cv = v->commentator;
else
cv = v;
if (qtv && qtv->controller == cv)
stats = qtv->players[qtv->thisplayer].stats;
else if (v->trackplayer == -1 || !qtv)
else if (cv->trackplayer == -1 || !qtv)
stats = nullstats;
else
stats = qtv->players[v->trackplayer].stats;
stats = qtv->players[cv->trackplayer].stats;
for (i = 0; i < MAX_STATS; i++)
{
@ -1986,6 +2059,32 @@ void PMove(viewer_t *v, usercmd_t *cmd)
v->velocity[2] = pmove.velocity[2];
}
void QW_SetCommentator(viewer_t *v, viewer_t *commentator)
{
// if (v->commentator == commentator)
// return;
WriteByte(&v->netchan.message, svc_setinfo);
WriteByte(&v->netchan.message, MAX_CLIENTS-2);
WriteString(&v->netchan.message, "name");
if (commentator)
{
WriteString(&v->netchan.message, commentator->name);
QW_StuffcmdToViewer(v, "cmd ptrack %i\n", MAX_CLIENTS-2);
QW_PrintfToViewer(v, "Following commentator %s\n", commentator->name);
if (v->server != commentator->server)
QW_SetViewersServer(v, commentator->server);
}
else
{
WriteString(&v->netchan.message, "");
if (v->commentator )
QW_PrintfToViewer(v, "Commentator disabled\n");
}
v->commentator = commentator;
}
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean noupwards)
{
char buf[1024];
@ -2378,6 +2477,42 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (remaining)
QW_PrintfToViewer(v, "%i clients not shown\n", remaining);
}
else if (!strncmp(message, ".followid ", 8))
{
int id = atoi(message+8);
viewer_t *cv;
for (cv = cluster->viewers; cv; cv = cv->next)
{
if (cv->userid == id)
{
QW_SetCommentator(v, cv);
return;
}
}
QW_PrintfToViewer(v, "Couldn't find that player\n");
QW_SetCommentator(v, NULL);
}
else if (!strncmp(message, ".follow ", 8))
{
char *id = message+8;
viewer_t *cv;
for (cv = cluster->viewers; cv; cv = cv->next)
{
if (!strcmp(cv->name, id))
{
QW_SetCommentator(v, cv);
return;
}
}
QW_PrintfToViewer(v, "Couldn't find that player\n");
QW_SetCommentator(v, NULL);
}
else if (!strncmp(message, ".follow", 7))
{
QW_SetCommentator(v, NULL);
}
else if (!strncmp(message, "proxy:menu up", 13))
{
v->menuop -= 1;
@ -2426,6 +2561,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
QW_StuffcmdToViewer(v, "bind downarrow +proxback\n");
QW_StuffcmdToViewer(v, "bind rightarrow +proxright\n");
QW_StuffcmdToViewer(v, "bind leftarrow +proxleft\n");
QW_PrintfToViewer(v, "Keys bound not recognised\n");
}
else if (!strncmp(message, ".menu bind", 10) || !strncmp(message, "proxy:menu bindstd", 18))
{
@ -2440,6 +2576,8 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
QW_StuffcmdToViewer(v, "bind end \"proxy:menu end\"\n");
QW_StuffcmdToViewer(v, "bind pause \"proxy:menu\"\n");
QW_StuffcmdToViewer(v, "bind backspace \"proxy:menu back\"\n");
QW_PrintfToViewer(v, "All keys bound not recognised\n");
}
else if (!strncmp(message, ".", 1) && strncmp(message, "..", 2))
{
@ -2860,6 +2998,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
}
else if (!strncmp(buf, "begin", 5))
{
viewer_t *com;
if (atoi(buf+6) != v->servercount)
SendServerData(qtv, v); //this is unfortunate!
else
@ -2871,6 +3010,10 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
SendBufferToViewer(v, msgb, sizeof(msgb), true);
}
}
com = v->commentator;
v->commentator = NULL;
QW_SetCommentator(v, com);
}
else if (!strncmp(buf, "download", 8))
{
@ -2901,9 +3044,16 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
QW_PrintfToViewer(v, "%s is not on the proxy, sorry\n", buf+5); //the apology is to make the alternatives distinct.
}
else if (!strncmp(buf, "ptrack ", 7))
{
v->trackplayer = atoi(buf+7);
// if (v->trackplayer != MAX_CLIENTS-2)
// QW_SetCommentator(v, NULL);
}
else if (!strncmp(buf, "ptrack", 6))
{
v->trackplayer = -1;
QW_SetCommentator(v, NULL);
}
else if (!strncmp(buf, "pings", 5))
{
}
@ -3364,6 +3514,7 @@ static const char dropcmd[] = {svc_stufftext, 'd', 'i', 's', 'c', 'o', 'n', 'n',
void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
{
viewer_t *oview;
int i;
//note: unlink them yourself.
@ -3388,6 +3539,12 @@ void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
viewer->server->numviewers--;
}
for (oview = cluster->viewers; oview; oview = oview->next)
{
if (oview->commentator == viewer)
QW_SetCommentator(oview, NULL);
}
free(viewer);
cluster->numviewers--;
@ -3436,6 +3593,9 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
continue;
}
// if (rand()&3)
// continue;
m.data = buffer;
m.cursize = read;
m.maxsize = MAX_MSGLEN;

View File

@ -518,10 +518,17 @@ char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffe
catbuffer(buffer, sizeofbuffer, "Connected\n");
if (qtv->parsingqtvheader || qtv->parsingconnectiondata)
catbuffer(buffer, sizeofbuffer, "Waiting for gamestate\n");
if (qtv->controller)
if (qtv->usequkeworldprotocols)
{
catbuffer(buffer, sizeofbuffer, "Spectating through %s\n");
catbuffer(buffer, sizeofbuffer, "QuakeWorld protocols\n");
if (qtv->controller)
{
catbuffer(buffer, sizeofbuffer, "Controlled by %s\n", qtv->controller->name);
}
}
else if (qtv->sourcesock == INVALID_SOCKET && !qtv->sourcefile)
catbuffer(buffer, sizeofbuffer, "Connection not established\n");
if (*qtv->modellist[1].name)
{
catbuffer(buffer, sizeofbuffer, "Map name %s\n", qtv->modellist[1].name);

View File

@ -490,7 +490,7 @@ qboolean Net_WriteUpStream(sv_t *qtv)
{
int len;
if (qtv->upstreambuffersize)
if (qtv->upstreambuffersize && qtv->sourcesock != INVALID_SOCKET)
{
len = send(qtv->sourcesock, qtv->upstreambuffer, qtv->upstreambuffersize, 0);
if (len == 0)
@ -589,6 +589,7 @@ qboolean Net_ReadStream(sv_t *qtv)
Sys_Printf(qtv->cluster, "Error: server %s refused connection\n", qtv->server);
closesocket(qtv->sourcesock);
qtv->sourcesock = INVALID_SOCKET;
qtv->upstreambuffersize = 0; //probably contains initial connection request info
return false;
}
@ -1049,7 +1050,7 @@ void QTV_ParseQWStream(sv_t *qtv)
strcpy(qtv->status, "Attemping connection\n");
qtv->challenge = atoi(buffer+5);
if (qtv->controller)
sprintf(buffer, "connect %i %i %i \"%s\\*qtv\\1\\\"", 28, qtv->qport, qtv->challenge, qtv->controller->userinfo);
sprintf(buffer, "connect %i %i %i \"%s\\*qtv\\1\"", 28, qtv->qport, qtv->challenge, qtv->controller->userinfo);
else if (qtv->proxyplayer)
sprintf(buffer, "connect %i %i %i \"%s\\name\\%s\"", 28, qtv->qport, qtv->challenge, "\\*ver\\fteqtv\\spectator\\0\\rate\\10000", qtv->cluster->hostname);
else
@ -1661,6 +1662,8 @@ void QTV_Run(sv_t *qtv)
Net_ReadStream(qtv);
qtv->parsetime += packettime;
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME;
}
else
break;