Cleaned up a little

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2529 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-07-23 10:53:59 +00:00
parent 7ef4972a5b
commit 9b24dd1871
15 changed files with 3827 additions and 3306 deletions

View File

@ -4,7 +4,7 @@ STRIP=strip
STRIPFLAGS=--strip-unneeded --remove-section=.comment
OBJS = netchan.o parse.o qw.o source.o bsp.o rcon.o mdfour.o crc.o control.o forward.o pmove.o httpsv.o
OBJS = netchan.o parse.o msg.o qw.o source.o bsp.o rcon.o mdfour.o crc.o control.o forward.o pmove.o httpsv.o
qtv: $(OBJS) qtv.h
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@.db -lm

View File

@ -43,7 +43,7 @@ struct bsp_s {
intermission_t intermissionspot[8];
};
static const intermission_t intermissionspot;
static const intermission_t nullintermissionspot;
typedef struct
@ -213,6 +213,8 @@ void BSP_LoadEntities(bsp_t *bsp, char *entitydata)
switch (etype)
{
case et_random: //a random (unknown) entity
break;
case et_primarystart: //a single player start
memcpy(startspotorg, org, sizeof(startspotorg));
memcpy(startspotangles, angles, sizeof(startspotangles));
@ -483,5 +485,6 @@ const intermission_t *BSP_IntermissionSpot(bsp_t *bsp)
return &bsp->intermissionspot[spotnum];
}
}
return &intermissionspot;
}
return &nullintermissionspot;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,94 +1,95 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* crc.c */
#include "qtv.h"
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define QCRC_INIT_VALUE 0xffff
#define QCRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void QCRC_Init(unsigned short *crcvalue)
{
*crcvalue = QCRC_INIT_VALUE;
}
void QCRC_ProcessByte(unsigned short *crcvalue, unsigned char data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short QCRC_Value(unsigned short crcvalue)
{
return crcvalue ^ QCRC_XOR_VALUE;
}
unsigned short QCRC_Block (unsigned char *start, int count)
{
unsigned short crc;
QCRC_Init (&crc);
while (count--)
crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++];
return crc;
}
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* crc.c */
#include "qtv.h"
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
// and the initial and final xor values shown below... in other words, the
// CCITT standard CRC used by XMODEM
#define QCRC_INIT_VALUE 0xffff
#define QCRC_XOR_VALUE 0x0000
static unsigned short crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
void QCRC_Init(unsigned short *crcvalue)
{
*crcvalue = QCRC_INIT_VALUE;
}
void QCRC_ProcessByte(unsigned short *crcvalue, unsigned char data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
unsigned short QCRC_Value(unsigned short crcvalue)
{
return crcvalue ^ QCRC_XOR_VALUE;
}
unsigned short QCRC_Block (void *start, int count)
{
unsigned char *data = start;
unsigned short crc;
QCRC_Init (&crc);
while (count--)
crc = (crc << 8) ^ crctable[(crc >> 8) ^ *data++];
return crc;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

146
fteqtv/msg.c Normal file
View File

@ -0,0 +1,146 @@
#include "qtv.h"
void InitNetMsg(netmsg_t *b, void *buffer, int bufferlength)
{
b->data = buffer;
b->maxsize = bufferlength;
b->readpos = 0;
b->cursize = 0;
}
unsigned char ReadByte(netmsg_t *b)
{
if (b->readpos >= b->cursize)
{
b->readpos = b->cursize+1;
return 0;
}
return ((unsigned char *)b->data)[b->readpos++];
}
unsigned short ReadShort(netmsg_t *b)
{
int b1, b2;
b1 = ReadByte(b);
b2 = ReadByte(b);
return b1 | (b2<<8);
}
unsigned int ReadLong(netmsg_t *b)
{
int s1, s2;
s1 = ReadShort(b);
s2 = ReadShort(b);
return s1 | (s2<<16);
}
unsigned int BigLong(unsigned int val)
{
union {
unsigned int i;
unsigned char c[4];
} v;
v.i = val;
return (v.c[0]<<24) | (v.c[1] << 16) | (v.c[2] << 8) | (v.c[3] << 0);
}
unsigned int SwapLong(unsigned int val)
{
union {
unsigned int i;
unsigned char c[4];
} v;
unsigned char s;
v.i = val;
s = v.c[0];
v.c[0] = v.c[3];
v.c[3] = s;
s = v.c[1];
v.c[1] = v.c[2];
v.c[2] = s;
return v.i;
}
float ReadFloat(netmsg_t *b)
{
union {
unsigned int i;
float f;
} u;
u.i = ReadLong(b);
return u.f;
}
void ReadString(netmsg_t *b, char *string, int maxlen)
{
maxlen--; //for null terminator
while(maxlen)
{
*string = ReadByte(b);
if (!*string)
return;
string++;
maxlen--;
}
*string++ = '\0'; //add the null
printf("ReadString: buffer is too small\n");
while(ReadByte(b)) //finish reading the string, even if we will loose part of it
;
}
void WriteByte(netmsg_t *b, unsigned char c)
{
if (b->cursize>=b->maxsize)
return;
((unsigned char*)b->data)[b->cursize++] = c;
}
void WriteShort(netmsg_t *b, unsigned short l)
{
WriteByte(b, (l&0x00ff)>>0);
WriteByte(b, (l&0xff00)>>8);
}
void WriteLong(netmsg_t *b, unsigned int l)
{
WriteByte(b, (l&0x000000ff)>>0);
WriteByte(b, (l&0x0000ff00)>>8);
WriteByte(b, (l&0x00ff0000)>>16);
WriteByte(b, (l&0xff000000)>>24);
}
void WriteFloat(netmsg_t *b, float f)
{
union {
unsigned int i;
float f;
} u;
u.f = f;
WriteLong(b, u.i);
}
void WriteString2(netmsg_t *b, const char *str)
{ //no null terminator, convienience function.
while(*str)
WriteByte(b, *str++);
}
void WriteString(netmsg_t *b, const char *str)
{
while(*str)
WriteByte(b, *str++);
WriteByte(b, 0);
}
void WriteData(netmsg_t *b, const void *data, int length)
{
int i;
unsigned char *buf;
if (b->cursize + length > b->maxsize) //urm, that's just too big. :(
return;
buf = b->data+b->cursize;
for (i = 0; i < length; i++)
*buf++ = ((unsigned char*)data)[i];
b->cursize+=length;
}

View File

@ -25,7 +25,7 @@ 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)
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, void *data, netadr_t adr)
{
int ret;
@ -120,7 +120,7 @@ Netchan_OutOfBand
Sends an out-of-band datagram
================
*/
void Netchan_OutOfBand (cluster_t *cluster, SOCKET sock, netadr_t adr, int length, unsigned char *data)
void Netchan_OutOfBand (cluster_t *cluster, SOCKET sock, netadr_t adr, int length, void *data)
{
netmsg_t send;
unsigned char send_buf[MAX_MSGLEN + PACKET_HEADER];
@ -205,7 +205,6 @@ Netchan_CanPacket
Returns true if the bandwidth choke isn't active
================
*/
#define MAX_BACKUP 200
qboolean Netchan_CanPacket (netchan_t *chan)
{
unsigned int t;
@ -214,7 +213,7 @@ qboolean Netchan_CanPacket (netchan_t *chan)
// return true;
t = curtime;
if (chan->cleartime < t + MAX_BACKUP*chan->rate)
if (chan->cleartime < t)
return true;
return false;
}
@ -244,7 +243,7 @@ transmition / retransmition of the reliable messages.
A 0 length will still generate a packet and deal with the reliable messages.
================
*/
void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const unsigned char *data)
void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const void *data)
{
unsigned int t;
netmsg_t send;
@ -291,9 +290,9 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const un
NET_SendPacket(cluster, chan->sock, send.cursize, send.data, chan->remote_address);
if (chan->cleartime < curtime)
chan->cleartime = curtime + send.cursize*chan->rate;
chan->cleartime = curtime + (int)(send.cursize*chan->rate);
else
chan->cleartime += send.cursize*chan->rate;
chan->cleartime += (int)(send.cursize*chan->rate);
}
//send out the unreliable (if still unsent)
@ -309,9 +308,9 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const un
NET_SendPacket (cluster, chan->sock, send.cursize, send.data, chan->remote_address);
if (chan->cleartime < curtime)
chan->cleartime = curtime + send.cursize*chan->rate;
chan->cleartime = (int)(curtime + send.cursize*chan->rate);
else
chan->cleartime += send.cursize*chan->rate;
chan->cleartime += (int)(send.cursize*chan->rate);
send.cursize = 0;
}
@ -386,9 +385,9 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const un
t = curtime;
if (chan->cleartime < t)
chan->cleartime = t + send.cursize*chan->rate;
chan->cleartime = t + (int)(send.cursize*chan->rate);
else
chan->cleartime += send.cursize*chan->rate;
chan->cleartime += (int)(send.cursize*chan->rate);
#ifndef CLIENTONLY
// if (chan->sock == NS_SERVER && sv_paused.value)
// chan->cleartime = curtime;

View File

@ -22,147 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ParseError(m) (m)->cursize = (m)->cursize+1 //
void InitNetMsg(netmsg_t *b, char *buffer, int bufferlength)
{
b->data = buffer;
b->maxsize = bufferlength;
b->readpos = 0;
b->cursize = 0;
}
//probably not the place for these any more..
unsigned char ReadByte(netmsg_t *b)
{
if (b->readpos >= b->cursize)
{
b->readpos = b->cursize+1;
return 0;
}
return b->data[b->readpos++];
}
unsigned short ReadShort(netmsg_t *b)
{
int b1, b2;
b1 = ReadByte(b);
b2 = ReadByte(b);
return b1 | (b2<<8);
}
unsigned int ReadLong(netmsg_t *b)
{
int s1, s2;
s1 = ReadShort(b);
s2 = ReadShort(b);
return s1 | (s2<<16);
}
unsigned int BigLong(unsigned int val)
{
union {
unsigned int i;
unsigned char c[4];
} v;
v.i = val;
return (v.c[0]<<24) | (v.c[1] << 16) | (v.c[2] << 8) | (v.c[3] << 0);
}
unsigned int SwapLong(unsigned int val)
{
union {
unsigned int i;
unsigned char c[4];
} v;
unsigned char s;
v.i = val;
s = v.c[0];
v.c[0] = v.c[3];
v.c[3] = s;
s = v.c[1];
v.c[1] = v.c[2];
v.c[2] = s;
return v.i;
}
float ReadFloat(netmsg_t *b)
{
union {
unsigned int i;
float f;
} u;
u.i = ReadLong(b);
return u.f;
}
void ReadString(netmsg_t *b, char *string, int maxlen)
{
maxlen--; //for null terminator
while(maxlen)
{
*string = ReadByte(b);
if (!*string)
return;
string++;
maxlen--;
}
*string++ = '\0'; //add the null
}
void WriteByte(netmsg_t *b, unsigned char c)
{
if (b->cursize>=b->maxsize)
return;
b->data[b->cursize++] = c;
}
void WriteShort(netmsg_t *b, unsigned short l)
{
WriteByte(b, (l&0x00ff)>>0);
WriteByte(b, (l&0xff00)>>8);
}
void WriteLong(netmsg_t *b, unsigned int l)
{
WriteByte(b, (l&0x000000ff)>>0);
WriteByte(b, (l&0x0000ff00)>>8);
WriteByte(b, (l&0x00ff0000)>>16);
WriteByte(b, (l&0xff000000)>>24);
}
void WriteFloat(netmsg_t *b, float f)
{
union {
unsigned int i;
float f;
} u;
u.f = f;
WriteLong(b, u.i);
}
void WriteString2(netmsg_t *b, const char *str)
{ //no null terminator, convienience function.
while(*str)
WriteByte(b, *str++);
}
void WriteString(netmsg_t *b, const char *str)
{
while(*str)
WriteByte(b, *str++);
WriteByte(b, 0);
}
void WriteData(netmsg_t *b, const char *data, int length)
{
int i;
unsigned char *buf;
if (b->cursize + length > b->maxsize) //urm, that's just too big. :(
return;
buf = b->data+b->cursize;
for (i = 0; i < length; i++)
*buf++ = *data++;
b->cursize+=length;
}
void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean reliable)
{
if (reliable)
@ -176,8 +35,11 @@ void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean re
{
v->netchan.message.cursize = 0;
WriteByte(&v->netchan.message, svc_print);
if (!v->netchan.isnqprotocol)
WriteByte(&v->netchan.message, PRINT_HIGH);
WriteString(&v->netchan.message, "backbuffer overflow\n");
Sys_Printf(NULL, "%s backbuffers overflowed\n", v->name); //FIXME
if (!v->drop)
Sys_Printf(NULL, "%s backbuffers overflowed\n", v->name); //FIXME
v->drop = true; //we would need too many backbuffers.
}
else
@ -194,7 +56,7 @@ void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean re
}
}
void Multicast(sv_t *tv, char *buffer, int length, int to, unsigned int playermask, int suitablefor)
void Multicast(sv_t *tv, void *buffer, int length, int to, unsigned int playermask, int suitablefor)
{
viewer_t *v;
switch(to)
@ -227,7 +89,7 @@ void Multicast(sv_t *tv, char *buffer, int length, int to, unsigned int playerma
break;
}
}
void Broadcast(cluster_t *cluster, char *buffer, int length, int suitablefor)
void Broadcast(cluster_t *cluster, void *buffer, int length, int suitablefor)
{
viewer_t *v;
for (v = cluster->viewers; v; v = v->next)
@ -237,6 +99,12 @@ void Broadcast(cluster_t *cluster, char *buffer, int length, int suitablefor)
}
}
void ConnectionData(sv_t *tv, void *buffer, int length, int to, unsigned int playermask, int suitablefor)
{
if (!tv->parsingconnectiondata)
Multicast(tv, buffer, length, to, playermask, suitablefor);
}
static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playermask)
{
int i;
@ -258,7 +126,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
ReadString(m, tv->gamedir, sizeof(tv->gamedir));
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
tv->thisplayer = ReadByte(m)&~128;
else
{
@ -306,7 +174,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
tv->frame[i].numents = 0;
}
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
tv->netchan.message.cursize = 0; //mvdsv sucks
SendClientCommand(tv, "soundlist %i 0\n", tv->clservercount);
@ -319,15 +187,12 @@ static void ParseCDTrack(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
char nqversion[3];
tv->cdtrack = ReadByte(m);
if (!tv->parsingconnectiondata)
{
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, QW);
ConnectionData(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, QW);
nqversion[0] = svc_cdtrack;
nqversion[1] = tv->cdtrack;
nqversion[2] = tv->cdtrack;
Multicast(tv, nqversion, 3, to, mask, NQ);
}
nqversion[0] = svc_cdtrack;
nqversion[1] = tv->cdtrack;
nqversion[2] = tv->cdtrack;
ConnectionData(tv, nqversion, 3, to, mask, NQ);
}
static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
{
@ -351,7 +216,13 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
QW_SetMenu(tv->controller, atoi(text+18)?MENU_FORWARDING:MENU_NONE);
}
else if (strstr(text, "screenshot"))
{
if (tv->controller)
{ //let it through to the controller
SendBufferToViewer(tv->controller, m->data+m->startpos, m->readpos - m->startpos, true);
}
return; //this was generating far too many screenshots when watching demos
}
else if (!strcmp(text, "skins\n"))
{
const char newcmd[10] = {svc_stufftext, 'c', 'm', 'd', ' ', 'n','e','w','\n','\0'};
@ -368,7 +239,7 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
}
}
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
SendClientCommand(tv, "begin %i\n", tv->clservercount);
return;
}
@ -415,22 +286,25 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
}
else if (!strncmp(text, "cmd ", 4))
{
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
SendClientCommand(tv, "%s", text+4);
return; //commands the game server asked for are pointless.
}
else if (!strncmp(text, "reconnect", 9))
{
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
SendClientCommand(tv, "new\n");
return;
}
else if (!strncmp(text, "packet ", 7))
{
if(tv->usequkeworldprotocols)
{//eeeevil hack
#define ARG_LEN 256
if (tv->controller)
{ //if we're acting as a proxy, forward the realip packets, and ONLY to the controller
SendBufferToViewer(tv->controller, m->data+m->startpos, m->readpos - m->startpos, true);
return;
}
if(tv->usequakeworldprotocols)
{//eeeevil hack for proxy-spectating
char *ptr;
char arg[3][ARG_LEN];
netadr_t adr;
@ -438,7 +312,7 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
ptr = COM_ParseToken(ptr, arg[0], ARG_LEN, "");
ptr = COM_ParseToken(ptr, arg[1], ARG_LEN, "");
ptr = COM_ParseToken(ptr, arg[2], ARG_LEN, "");
NET_StringToAddr(arg[1], &adr, 27500);
NET_StringToAddr(arg[1], &adr, PROX_DEFAULTSERVERPORT);
Netchan_OutOfBand(tv->cluster, tv->sourcesock, adr, strlen(arg[2]), arg[2]);
//this is an evil hack
@ -448,7 +322,7 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
tv->drop = true; //this shouldn't ever happen
return;
}
else if (tv->usequkeworldprotocols && !strncmp(text, "setinfo ", 8))
else if (tv->usequakeworldprotocols && !strncmp(text, "setinfo ", 8))
{
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, Q1);
SendClientCommand(tv, text);
@ -472,8 +346,7 @@ static void ParseSetInfo(sv_t *tv, netmsg_t *m)
if (pnum < MAX_CLIENTS)
Info_SetValueForStarKey(tv->players[pnum].userinfo, key, value, sizeof(tv->players[pnum].userinfo));
if (!tv->parsingconnectiondata)
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, dem_all, (unsigned)-1, QW);
ConnectionData(tv, m->data+m->startpos, m->readpos - m->startpos, dem_all, (unsigned)-1, QW);
}
static void ParseServerinfo(sv_t *tv, netmsg_t *m)
@ -486,8 +359,7 @@ static void ParseServerinfo(sv_t *tv, netmsg_t *m)
if (strcmp(key, "hostname")) //don't allow the hostname to change, but allow the server to change other serverinfos.
Info_SetValueForStarKey(tv->serverinfo, key, value, sizeof(tv->serverinfo));
if (!tv->parsingconnectiondata)
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, dem_all, (unsigned)-1, QW);
ConnectionData(tv, m->data+m->startpos, m->readpos - m->startpos, dem_all, (unsigned)-1, QW);
}
static void ParsePrint(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
@ -510,7 +382,7 @@ static void ParsePrint(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
}
buffer[0] = svc_print;
if (to == dem_all || to == dem_read)
if ((to&dem_mask) == dem_all || to == dem_read)
{
if (level > 1)
{
@ -619,8 +491,8 @@ static void ParseStaticSound(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
tv->staticsound[tv->staticsound_count].attenuation = ReadByte(m);
tv->staticsound_count++;
if (!tv->parsingconnectiondata)
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, Q1);
ConnectionData(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, Q1);
}
static void ParseIntermission(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
@ -647,8 +519,7 @@ void ParseSpawnStatic(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
tv->spawnstatic_count++;
if (!tv->parsingconnectiondata)
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, Q1);
ConnectionData(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask, Q1);
}
extern const usercmd_t nullcmd;
@ -676,7 +547,7 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
}
tv->players[num].old = tv->players[num].current;
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
tv->players[num].old = tv->players[num].current;
flags = (unsigned short)ReadShort (m);
@ -790,7 +661,6 @@ static int readentitynum(netmsg_t *m, unsigned int *retflags)
{
int entnum;
unsigned int flags;
unsigned short moreflags = 0;
flags = ReadShort(m);
if (!flags)
{
@ -925,7 +795,7 @@ static void ParsePacketEntities(sv_t *tv, netmsg_t *m, int deltaframe)
if (deltaframe != -1)
deltaframe &= (ENTITY_FRAMES-1);
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
newframe = &tv->frame[tv->netchan.incoming_sequence & (ENTITY_FRAMES-1)];
@ -1457,7 +1327,7 @@ void ParseNails(sv_t *tv, netmsg_t *m, qboolean nails2)
int i;
count = (unsigned char)ReadByte(m);
while(count > sizeof(tv->nails) / sizeof(tv->nails[0]))
{
{//they sent too many, suck it out.
count--;
if (nails2)
ReadByte(m);
@ -1537,7 +1407,7 @@ void ParseDownload(sv_t *tv, netmsg_t *m)
}
}
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
void ParseMessage(sv_t *tv, void *buffer, int length, int to, int mask)
{
int i;
netmsg_t buf;
@ -1571,8 +1441,16 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
//the client is meant to read that and disconnect without reading the intentionally corrupt packet following it.
//however, our demo playback is chained and looping and buffered.
//so we've already found the end of the source file and restarted parsing.
//so there's very little we can do except crash ourselves on the EndOfDemo text following the svc_disconnect
//that's a bad plan, so just stop reading this packet.
//in fte at least, the server does give the packet the correct length
//I hope mvdsv is the same
if (tv->sourcetype != SRC_DEMO)
tv->drop = true;
else
{
while(ReadByte(&buf))
;
}
return;
case svc_updatestat:
@ -1580,11 +1458,17 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
break;
//#define svc_version 4 // [long] server version
//#define svc_setview 5 // [short] entity number
case svc_nqsetview:
ReadShort(&buf);
//no actual handling is done!
break;
case svc_sound:
ParseSound(tv, &buf, to, mask);
break;
//#define svc_time 7 // [float] server time
case svc_nqtime:
ReadFloat(&buf);
//no actual handling is done!
break;
case svc_print:
ParsePrint(tv, &buf, to, mask);
@ -1595,13 +1479,13 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
break;
case svc_setangle:
if (!tv->usequkeworldprotocols)
if (!tv->usequakeworldprotocols)
ReadByte(&buf);
tv->proxyplayerangles[0] = ReadByte(&buf)*360.0/255;
tv->proxyplayerangles[1] = ReadByte(&buf)*360.0/255;
tv->proxyplayerangles[2] = ReadByte(&buf)*360.0/255;
if (tv->usequkeworldprotocols && tv->controller)
if (tv->usequakeworldprotocols && tv->controller)
SendBufferToViewer(tv->controller, buf.data+buf.startpos, buf.readpos - buf.startpos, true);
{
@ -1672,9 +1556,6 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
ParseCenterprint(tv, &buf, to, mask);
break;
//#define svc_killedmonster 27
//#define svc_foundsecret 28
case svc_spawnstaticsound:
ParseStaticSound(tv, &buf, to, mask);
break;
@ -1683,13 +1564,19 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
ParseIntermission(tv, &buf, to, mask);
break;
//#define svc_finale 31 // [string] text
case svc_finale:
while(ReadByte(&buf))
;
Multicast(tv, buf.data+buf.startpos, buf.readpos - buf.startpos, dem_read, (unsigned)-1, Q1);
break;
case svc_cdtrack:
ParseCDTrack(tv, &buf, to, mask);
break;
//#define svc_sellscreen 33
case svc_sellscreen:
Multicast(tv, buf.data+buf.startpos, buf.readpos - buf.startpos, dem_read, (unsigned)-1, Q1);
break;
//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt?
@ -1757,7 +1644,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
}
strcpy(tv->status, "Prespawning\n");
}
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
if (i)
SendClientCommand(tv, "modellist %i %i\n", tv->clservercount, i);
@ -1795,7 +1682,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
i = ParseList(tv, &buf, tv->soundlist, to, mask);
if (!i)
strcpy(tv->status, "Receiving modellist\n");
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
if (i)
SendClientCommand(tv, "soundlist %i %i\n", tv->clservercount, i);

View File

@ -1,161 +1,164 @@
#include "qtv.h"
#include <math.h>
#define M_PI 3.1415926535897932384626433832795
void AngleVectors (vec3_t angles, float *forward, float *right, float *up)
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[1] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[0] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[2] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
right[1] = (-1*sr*sp*sy+-1*cr*cy);
right[2] = -1*sr*cp;
up[0] = (cr*sp*cy+-sr*-sy);
up[1] = (cr*sp*sy+-sr*cy);
up[2] = cr*cp;
}
#define DotProduct(a,b) ((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]))
#define VectorCopy(a,b) do{b[0]=a[0];b[1]=a[1];b[2]=a[2];}while(0)
#define VectorClear(v) do{v[0]=0;v[1]=0;v[2]=0;}while(0)
#define VectorScale(i,s,o) do{o[0]=i[0]*s;o[1]=i[1]*s;o[2]=i[2]*s;}while(0)
#define Length(v) sqrt(DotProduct(v, v))
#define VectorMA(base,s,m,out) do{out[0]=base[0]+s*m[0];out[1]=base[1]+s*m[1];out[2]=base[2]+s*m[2];}while(0)
#define SHORT2ANGLE(s) ((s*360.0f)/65536)
float VectorNormalize(vec3_t v)
{
float len, ilen;
len = Length(v);
if (len)
{
ilen = 1/len;
v[0] *= ilen;
v[1] *= ilen;
v[2] *= ilen;
}
return len;
}
void PM_SpectatorMove (pmove_t *pmove)
{
float speed, drop, friction, control, newspeed;
float currentspeed, addspeed, accelspeed;
int i;
vec3_t wishvel;
float fmove, smove;
vec3_t wishdir;
float wishspeed;
// friction
speed = Length (pmove->velocity);
if (speed < 1)
{
VectorClear (pmove->velocity);
}
else
{
drop = 0;
friction = pmove->movevars.friction*1.5; // extra friction
control = speed < pmove->movevars.stopspeed ? pmove->movevars.stopspeed : speed;
drop += control*friction*pmove->frametime;
// scale the velocity
newspeed = speed - drop;
if (newspeed < 0)
newspeed = 0;
newspeed /= speed;
VectorScale (pmove->velocity, newspeed, pmove->velocity);
}
// accelerate
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
VectorNormalize (pmove->forward);
VectorNormalize (pmove->right);
for (i=0 ; i<3 ; i++)
wishvel[i] = pmove->forward[i]*fmove + pmove->right[i]*smove;
wishvel[2] += pmove->cmd.upmove;
VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(wishdir);
//
// clamp to server defined max speed
//
if (wishspeed > pmove->movevars.spectatormaxspeed)
{
VectorScale (wishvel, pmove->movevars.spectatormaxspeed/wishspeed, wishvel);
wishspeed = pmove->movevars.spectatormaxspeed;
}
currentspeed = DotProduct(pmove->velocity, wishdir);
addspeed = wishspeed - currentspeed;
// Buggy QW spectator mode, kept for compatibility
// if (pmove->pm_type == PM_OLD_SPECTATOR)
{
if (addspeed <= 0)
return;
}
if (addspeed > 0)
{
accelspeed = pmove->movevars.accelerate*pmove->frametime*wishspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
pmove->velocity[i] += accelspeed*wishdir[i];
}
// move
VectorMA (pmove->origin, pmove->frametime, pmove->velocity, pmove->origin);
}
void PM_PlayerMove (pmove_t *pmove)
{
pmove->frametime = pmove->cmd.msec * 0.001;
/*
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE)
{
PM_CategorizePosition ();
return;
}
*/
// take angles directly from command
pmove->angles[0] = SHORT2ANGLE(pmove->cmd.angles[0]);
pmove->angles[1] = SHORT2ANGLE(pmove->cmd.angles[1]);
pmove->angles[2] = SHORT2ANGLE(pmove->cmd.angles[2]);
AngleVectors (pmove->angles, pmove->forward, pmove->right, pmove->up);
// if (pmove->pm_type == PM_SPECTATOR || pmove->pm_type == PM_OLD_SPECTATOR)
{
PM_SpectatorMove (pmove);
// pmove->onground = false;
return;
}
}
#include "qtv.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
void AngleVectors (vec3_t angles, float *forward, float *right, float *up)
{
float angle;
float sr, sp, sy, cr, cp, cy;
angle = angles[1] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[0] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[2] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
right[1] = (-1*sr*sp*sy+-1*cr*cy);
right[2] = -1*sr*cp;
up[0] = (cr*sp*cy+-sr*-sy);
up[1] = (cr*sp*sy+-sr*cy);
up[2] = cr*cp;
}
#define DotProduct(a,b) ((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]))
#define VectorCopy(a,b) do{b[0]=a[0];b[1]=a[1];b[2]=a[2];}while(0)
#define VectorClear(v) do{v[0]=0;v[1]=0;v[2]=0;}while(0)
#define VectorScale(i,s,o) do{o[0]=i[0]*s;o[1]=i[1]*s;o[2]=i[2]*s;}while(0)
#define Length(v) sqrt(DotProduct(v, v))
#define VectorMA(base,s,m,out) do{out[0]=base[0]+s*m[0];out[1]=base[1]+s*m[1];out[2]=base[2]+s*m[2];}while(0)
#define SHORT2ANGLE(s) ((s*360.0f)/65536)
float VectorNormalize(vec3_t v)
{
float len, ilen;
len = Length(v);
if (len)
{
ilen = 1/len;
v[0] *= ilen;
v[1] *= ilen;
v[2] *= ilen;
}
return len;
}
void PM_SpectatorMove (pmove_t *pmove)
{
float speed, drop, friction, control, newspeed;
float currentspeed, addspeed, accelspeed;
int i;
vec3_t wishvel;
float fmove, smove;
vec3_t wishdir;
float wishspeed;
// friction
speed = Length (pmove->velocity);
if (speed < 1)
{
VectorClear (pmove->velocity);
}
else
{
drop = 0;
friction = pmove->movevars.friction*1.5; // extra friction
control = speed < pmove->movevars.stopspeed ? pmove->movevars.stopspeed : speed;
drop += control*friction*pmove->frametime;
// scale the velocity
newspeed = speed - drop;
if (newspeed < 0)
newspeed = 0;
newspeed /= speed;
VectorScale (pmove->velocity, newspeed, pmove->velocity);
}
// accelerate
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
VectorNormalize (pmove->forward);
VectorNormalize (pmove->right);
for (i=0 ; i<3 ; i++)
wishvel[i] = pmove->forward[i]*fmove + pmove->right[i]*smove;
wishvel[2] += pmove->cmd.upmove;
VectorCopy (wishvel, wishdir);
wishspeed = VectorNormalize(wishdir);
//
// clamp to server defined max speed
//
if (wishspeed > pmove->movevars.spectatormaxspeed)
{
VectorScale (wishvel, pmove->movevars.spectatormaxspeed/wishspeed, wishvel);
wishspeed = pmove->movevars.spectatormaxspeed;
}
currentspeed = DotProduct(pmove->velocity, wishdir);
addspeed = wishspeed - currentspeed;
// Buggy QW spectator mode, kept for compatibility
// if (pmove->pm_type == PM_OLD_SPECTATOR)
{
if (addspeed <= 0)
return;
}
if (addspeed > 0)
{
accelspeed = pmove->movevars.accelerate*pmove->frametime*wishspeed;
if (accelspeed > addspeed)
accelspeed = addspeed;
for (i=0 ; i<3 ; i++)
pmove->velocity[i] += accelspeed*wishdir[i];
}
// move
VectorMA (pmove->origin, pmove->frametime, pmove->velocity, pmove->origin);
}
void PM_PlayerMove (pmove_t *pmove)
{
pmove->frametime = pmove->cmd.msec * 0.001;
/*
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE)
{
PM_CategorizePosition ();
return;
}
*/
// take angles directly from command
pmove->angles[0] = SHORT2ANGLE(pmove->cmd.angles[0]);
pmove->angles[1] = SHORT2ANGLE(pmove->cmd.angles[1]);
pmove->angles[2] = SHORT2ANGLE(pmove->cmd.angles[2]);
AngleVectors (pmove->angles, pmove->forward, pmove->right, pmove->up);
// if (pmove->pm_type == PM_SPECTATOR || pmove->pm_type == PM_OLD_SPECTATOR)
{
PM_SpectatorMove (pmove);
// pmove->onground = false;
return;
}
}

256
fteqtv/protocol.h Normal file
View File

@ -0,0 +1,256 @@
//limitations of the protocol
#define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here.
#define MAX_USERINFO 192
#define MAX_CLIENTS 32
#define MAX_LIST 256
#define MAX_MODELS MAX_LIST
#define MAX_SOUNDS MAX_LIST
#define MAX_ENTITIES 512
#define MAX_STATICSOUNDS 64
#define MAX_STATICENTITIES 128
#define MAX_LIGHTSTYLES 64
#define MAX_PROXY_INBUFFER 4096
#define MAX_PROXY_BUFFER (1<<14) //must be power-of-two
#define PREFERED_PROXY_BUFFER 4096 //the ammount of data we try to leave in our input buffer (must be large enough to contain any single mvd frame)
#define ENTS_PER_FRAME 64 //max number of entities per frame (OUCH!).
#define ENTITY_FRAMES 64 //number of frames to remember for deltaing
#define Z_EXT_SERVERTIME (1<<3) // STAT_TIME
#define Z_EXT_STRING "8"
//qw specific
#define PRINT_CHAT 3
#define PRINT_HIGH 2
#define PRINT_MEDIUM 1
#define PRINT_LOW 0
#define MAX_STATS 32
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
#define STAT_ITEMS 15
#define STAT_TIME 17 //A ZQ hack, sending time via a stat.
//this allows l33t engines to interpolate properly without spamming at a silly high fps.
//limits
#define NQ_PACKETS_PER_SECOND 20
#define MAX_NQMSGLEN 8000
#define MAX_MSGLEN 1400
#define MAX_NQDATAGRAM 1024
#define MAX_BACKBUF_SIZE 1000 //this is smaller so we don't loose entities when lagging
//NQ transport layer defines
#define NETFLAG_LENGTH_MASK 0x0000ffff
#define NETFLAG_DATA 0x00010000
#define NETFLAG_ACK 0x00020000
#define NETFLAG_NAK 0x00040000
#define NETFLAG_EOM 0x00080000
#define NETFLAG_UNRELIABLE 0x00100000
#define NETFLAG_CTL 0x80000000
#define CCREQ_CONNECT 0x01
#define CCREQ_SERVER_INFO 0x02
#define CCREP_ACCEPT 0x81
#define CCREP_REJECT 0x82
#define CCREP_SERVER_INFO 0x83
#define NET_GAMENAME_NQ "QUAKE"
#define NET_PROTOCOL_VERSION 3
//end NQ specific
//the clcs sent via the udp connections
enum {
clc_bad = 0,
clc_nop = 1,
clc_disconnect = 2, //NQ only
clc_move = 3, // [[usercmd_t]
clc_stringcmd = 4, // [string] message
clc_delta = 5, // [byte] sequence number, requests delta compression of message
clc_tmove = 6, // teleport request, spectator only
clc_upload = 7 // teleport request, spectator only
};
//these are the clcs sent upstream via the tcp streams
enum {
qtv_clc_bad = 0,
qtv_clc_stringcmd = 1,
qtv_clc_commentarydata = 8
};
#define svc_bad 0
#define svc_nop 1
#define svc_disconnect 2
#define svc_updatestat 3 // [qbyte] [qbyte]
//#define svc_version 4 // [long] server version (not used anywhere)
#define svc_nqsetview 5 // [short] entity number
#define svc_sound 6 // <see code>
#define svc_nqtime 7 // [float] server time
#define svc_print 8 // [qbyte] id [string] null terminated string
#define svc_stufftext 9 // [string] stuffed into client's console buffer
// the string should be \n terminated
#define svc_setangle 10 // [angle3] set the view angle to this absolute value
#define svc_serverdata 11 // [long] protocol ...
#define svc_lightstyle 12 // [qbyte] [string]
#define svc_nqupdatename 13 // [qbyte] [string]
#define svc_updatefrags 14 // [qbyte] [short]
#define svc_nqclientdata 15 // <shortbits + data>
//#define svc_stopsound 16 // <see code> (not used anywhere)
#define svc_nqupdatecolors 17 // [qbyte] [qbyte] [qbyte]
#define svc_particle 18 // [vec3] <variable>
#define svc_damage 19
#define svc_spawnstatic 20
//#define svc_spawnstatic2 21 (not used anywhere)
#define svc_spawnbaseline 22
#define svc_temp_entity 23 // variable
#define svc_setpause 24 // [qbyte] on / off
#define svc_nqsignonnum 25 // [qbyte] used for the signon sequence
#define svc_centerprint 26 // [string] to put in center of the screen
#define svc_killedmonster 27
#define svc_foundsecret 28
#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten
#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle (show scoreboard and stuff)
#define svc_finale 31 // [string] text ('congratulations blah blah')
#define svc_cdtrack 32 // [qbyte] track
#define svc_sellscreen 33
//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt? (intermission without the scores)
#define svc_smallkick 34 // set client punchangle to 2
#define svc_bigkick 35 // set client punchangle to 4
#define svc_updateping 36 // [qbyte] [short]
#define svc_updateentertime 37 // [qbyte] [float]
#define svc_updatestatlong 38 // [qbyte] [long]
#define svc_muzzleflash 39 // [short] entity
#define svc_updateuserinfo 40 // [qbyte] slot [long] uid
// [string] userinfo
#define svc_download 41 // [short] size [size bytes]
#define svc_playerinfo 42 // variable
#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8
#define svc_chokecount 44 // [qbyte] packets choked
#define svc_modellist 45 // [strings]
#define svc_soundlist 46 // [strings]
#define svc_packetentities 47 // [...]
#define svc_deltapacketentities 48 // [...]
#define svc_maxspeed 49 // maxspeed change, for prediction
#define svc_entgravity 50 // gravity change, for prediction
#define svc_setinfo 51 // setinfo on a client
#define svc_serverinfo 52 // serverinfo
#define svc_updatepl 53 // [qbyte] [qbyte]
#define svc_nails2 54 //mvd only - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8
#define dem_audio 0
#define dem_cmd 0
#define dem_read 1
#define dem_set 2
#define dem_multiple 3
#define dem_single 4
#define dem_stats 5
#define dem_all 6
#define dem_qtvdata (dem_all | (1<<4)) //special packet that contains qtv data (spectator chat, etc. clients need to parse this as soon as it is sent to them, which might or might not be awkward for them)
#define dem_mask 7
#define PROTOCOL_VERSION_NQ 15
#define PROTOCOL_VERSION 28
//flags on entities
#define U_ORIGIN1 (1<<9)
#define U_ORIGIN2 (1<<10)
#define U_ORIGIN3 (1<<11)
#define U_ANGLE2 (1<<12)
#define U_FRAME (1<<13)
#define U_REMOVE (1<<14) // REMOVE this entity, don't add it
#define U_MOREBITS (1<<15)
// if MOREBITS is set, these additional flags are read in next
#define U_ANGLE1 (1<<0)
#define U_ANGLE3 (1<<1)
#define U_MODEL (1<<2)
#define U_COLORMAP (1<<3)
#define U_SKIN (1<<4)
#define U_EFFECTS (1<<5)
#define U_SOLID (1<<6) // the entity should be solid for prediction
//flags on players
#define PF_MSEC (1<<0)
#define PF_COMMAND (1<<1)
#define PF_VELOCITY1 (1<<2)
#define PF_VELOCITY2 (1<<3)
#define PF_VELOCITY3 (1<<4)
#define PF_MODEL (1<<5)
#define PF_SKINNUM (1<<6)
#define PF_EFFECTS (1<<7)
#define PF_WEAPONFRAME (1<<8) // only sent for view player
#define PF_DEAD (1<<9) // don't block movement any more
#define PF_GIB (1<<10) // offset the view height differently
//flags on players in mvds
#define DF_ORIGIN 1
#define DF_ANGLES (1<<3)
#define DF_EFFECTS (1<<6)
#define DF_SKINNUM (1<<7)
#define DF_DEAD (1<<8)
#define DF_GIB (1<<9)
#define DF_WEAPONFRAME (1<<10)
#define DF_MODEL (1<<11)

View File

@ -141,8 +141,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define strnicmp strncasecmp
#endif
#define ustrlen(s) strlen((char*)(s))
#define ustrcmp(s1,s2) strcmp((char*)(s1),(char*)(s2))
#define ustrncmp(s1,s2,l) strncmp((char*)(s1),(char*)(s2),l)
//linux and other systems have strlcat / strlcpy
//some systems have strlcat / strlcpy
//we support windows and can't use those
#define Q_strncatz(dest, src, sizeofdest) \
do { \
@ -161,54 +164,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define VERSION "0.01" //this will be added to the serverinfo
#define PROX_DEFAULTSERVERPORT 27500
#define PROX_DEFAULTLISTENPORT 27501
#define PROX_DEFAULTSERVER "localhost:27500"
#define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here.
#define MAX_USERINFO 192
#define MAX_CLIENTS 32
#define MAX_LIST 256
#define MAX_MODELS MAX_LIST
#define MAX_SOUNDS MAX_LIST
#define MAX_ENTITIES 512
#define MAX_STATICSOUNDS 64
#define MAX_STATICENTITIES 128
#define MAX_LIGHTSTYLES 64
#define DEFAULT_HOSTNAME "FTEQTV"
#define MAX_PROXY_INBUFFER 4096
#define MAX_PROXY_BUFFER (1<<14) //must be power-of-two
#define PREFERED_PROXY_BUFFER 4096 //the ammount of data we try to leave in our input buffer (must be large enough to contain any single mvd frame)
#define MAX_ENTITY_LEAFS 32
#define ENTS_PER_FRAME 64 //max number of entities per frame (OUCH!).
#define ENTITY_FRAMES 64 //number of frames to remember for deltaing
#define Z_EXT_SERVERTIME (1<<3) // STAT_TIME
#define Z_EXT_STRING "8"
#define MAX_STATS 32
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
#define STAT_ITEMS 15
#define STAT_TIME 17 //A ZQ hack, sending time via a stat.
//this allows l33t engines to interpolate properly without spamming at a silly high fps.
#include "protocol.h"
@ -222,31 +187,6 @@ extern "C" {
typedef unsigned char netadr_t[64];
#define NQ_PACKETS_PER_SECOND 20
#define MAX_NQMSGLEN 8000
#define MAX_MSGLEN 1400
#define MAX_NQDATAGRAM 1024
#define MAX_BACKBUF_SIZE 1000 //this is smaller so we don't loose entities when lagging
//NQ transport layer defines
#define NETFLAG_LENGTH_MASK 0x0000ffff
#define NETFLAG_DATA 0x00010000
#define NETFLAG_ACK 0x00020000
#define NETFLAG_NAK 0x00040000
#define NETFLAG_EOM 0x00080000
#define NETFLAG_UNRELIABLE 0x00100000
#define NETFLAG_CTL 0x80000000
#define CCREQ_CONNECT 0x01
#define CCREQ_SERVER_INFO 0x02
#define CCREP_ACCEPT 0x81
#define CCREP_REJECT 0x82
#define CCREP_SERVER_INFO 0x83
#define NET_GAMENAME_NQ "QUAKE"
#define NET_PROTOCOL_VERSION 3
#ifdef COMMENTARY
typedef struct soundcapt_s {
@ -263,7 +203,7 @@ typedef struct {
unsigned int readpos;
unsigned int cursize;
unsigned int maxsize;
char *data;
void *data;
unsigned int startpos;
qboolean overflowed;
qboolean allowoverflow;
@ -456,6 +396,7 @@ typedef struct oproxy_s {
qboolean drop;
sv_t *defaultstream;
sv_t *stream;
FILE *srcfile; //buffer is padded with data from this file when its empty
FILE *file; //recording a demo (written to)
@ -508,26 +449,38 @@ typedef struct {
float angle[3];
} intermission_t;
typedef enum {
SRC_BAD,
SRC_DEMO,
SRC_UDP,
SRC_TCP
} sourcetype_t;
struct sv_s { //details about a server connection (also known as stream)
char connectpassword[64]; //password given to server
netadr_t serveraddress;
netchan_t netchan;
qboolean serverquery;
sourcetype_t sourcetype;
//proxy chaining
qboolean serverisproxy;
qboolean proxyisselected;
qboolean upstreamacceptschat;
qboolean upstreamacceptsdownload;
//
unsigned char buffer[MAX_PROXY_BUFFER]; //this doesn't cycle.
int buffersize; //it memmoves down
int forwardpoint; //the point in the stream that we're forwarded up to.
int forwardpoint; //the point in the stream that we've forwarded up to.
qboolean parsingqtvheader;
unsigned char upstreambuffer[2048];
int upstreambuffersize;
unsigned int parsetime;
unsigned int parsespeed;
char gamedir[MAX_QPATH];
char mapname[256];
@ -561,7 +514,7 @@ struct sv_s { //details about a server connection (also known as stream)
qboolean silentstream;
qboolean usequkeworldprotocols;
qboolean usequakeworldprotocols;
int challenge;
unsigned short qport;
int isconnected;
@ -658,6 +611,7 @@ struct cluster_s {
char qtvpassword[256]; //password required to connect a proxy
char hostname[256];
char master[MAX_QPATH];
char demodir[MAX_QPATH];
qboolean chokeonnotupdated;
qboolean lateforward;
qboolean notalking;
@ -676,7 +630,6 @@ struct cluster_s {
oproxy_t *pendingproxies;
char demodir[128];
availdemo_t availdemos[2048];
int availdemoscount;
};
@ -722,170 +675,16 @@ unsigned int BigLong(unsigned int val);
#define clc_bad 0
#define clc_nop 1
#define clc_disconnect 2 //NQ only
#define clc_move 3 // [[usercmd_t]
#define clc_stringcmd 4 // [string] message
#define clc_delta 5 // [byte] sequence number, requests delta compression of message
#define clc_tmove 6 // teleport request, spectator only
#define clc_upload 7 // teleport request, spectator only
#define svc_bad 0
#define svc_nop 1
#define svc_disconnect 2
#define svc_updatestat 3 // [qbyte] [qbyte]
//#define svc_version 4 // [long] server version
#define svc_nqsetview 5 // [short] entity number
#define svc_sound 6 // <see code>
#define svc_nqtime 7 // [float] server time
#define svc_print 8 // [qbyte] id [string] null terminated string
#define svc_stufftext 9 // [string] stuffed into client's console buffer
// the string should be \n terminated
#define svc_setangle 10 // [angle3] set the view angle to this absolute value
#define svc_serverdata 11 // [long] protocol ...
#define svc_lightstyle 12 // [qbyte] [string]
#define svc_nqupdatename 13 // [qbyte] [string]
#define svc_updatefrags 14 // [qbyte] [short]
#define svc_nqclientdata 15 // <shortbits + data>
//#define svc_stopsound 16 // <see code>
#define svc_nqupdatecolors 17 // [qbyte] [qbyte] [qbyte]
#define svc_particle 18 // [vec3] <variable>
#define svc_damage 19
#define svc_spawnstatic 20
//#define svc_spawnstatic2 21
#define svc_spawnbaseline 22
#define svc_temp_entity 23 // variable
#define svc_setpause 24 // [qbyte] on / off
#define svc_nqsignonnum 25 // [qbyte] used for the signon sequence
#define svc_centerprint 26 // [string] to put in center of the screen
#define svc_killedmonster 27
#define svc_foundsecret 28
#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten
#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle
//#define svc_finale 31 // [string] text
#define svc_cdtrack 32 // [qbyte] track
//#define svc_sellscreen 33
//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt?
#define svc_smallkick 34 // set client punchangle to 2
#define svc_bigkick 35 // set client punchangle to 4
#define svc_updateping 36 // [qbyte] [short]
#define svc_updateentertime 37 // [qbyte] [float]
#define svc_updatestatlong 38 // [qbyte] [long]
#define svc_muzzleflash 39 // [short] entity
#define svc_updateuserinfo 40 // [qbyte] slot [long] uid
// [string] userinfo
#define svc_download 41 // [short] size [size bytes]
#define svc_playerinfo 42 // variable
#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8
#define svc_chokecount 44 // [qbyte] packets choked
#define svc_modellist 45 // [strings]
#define svc_soundlist 46 // [strings]
#define svc_packetentities 47 // [...]
#define svc_deltapacketentities 48 // [...]
#define svc_maxspeed 49 // maxspeed change, for prediction
#define svc_entgravity 50 // gravity change, for prediction
#define svc_setinfo 51 // setinfo on a client
#define svc_serverinfo 52 // serverinfo
#define svc_updatepl 53 // [qbyte] [qbyte]
#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8
#define dem_audio 0
#define dem_cmd 0
#define dem_read 1
#define dem_set 2
#define dem_multiple 3
#define dem_single 4
#define dem_stats 5
#define dem_all 6
#define dem_mask 7
#define PROTOCOL_VERSION_NQ 15
#define PROTOCOL_VERSION 28
//flags on entities
#define U_ORIGIN1 (1<<9)
#define U_ORIGIN2 (1<<10)
#define U_ORIGIN3 (1<<11)
#define U_ANGLE2 (1<<12)
#define U_FRAME (1<<13)
#define U_REMOVE (1<<14) // REMOVE this entity, don't add it
#define U_MOREBITS (1<<15)
// if MOREBITS is set, these additional flags are read in next
#define U_ANGLE1 (1<<0)
#define U_ANGLE3 (1<<1)
#define U_MODEL (1<<2)
#define U_COLORMAP (1<<3)
#define U_SKIN (1<<4)
#define U_EFFECTS (1<<5)
#define U_SOLID (1<<6) // the entity should be solid for prediction
//flags on players
#define PF_MSEC (1<<0)
#define PF_COMMAND (1<<1)
#define PF_VELOCITY1 (1<<2)
#define PF_VELOCITY2 (1<<3)
#define PF_VELOCITY3 (1<<4)
#define PF_MODEL (1<<5)
#define PF_SKINNUM (1<<6)
#define PF_EFFECTS (1<<7)
#define PF_WEAPONFRAME (1<<8) // only sent for view player
#define PF_DEAD (1<<9) // don't block movement any more
#define PF_GIB (1<<10) // offset the view height differently
//flags on players in mvds
#define DF_ORIGIN 1
#define DF_ANGLES (1<<3)
#define DF_EFFECTS (1<<6)
#define DF_SKINNUM (1<<7)
#define DF_DEAD (1<<8)
#define DF_GIB (1<<9)
#define DF_WEAPONFRAME (1<<10)
#define DF_MODEL (1<<11)
//flags for where a message can be sent, for easy broadcasting
#define Q1 (NQ|QW)
#define QW 1
#define NQ 2
#define CONNECTING 4
#include "cmd.h"
void InitNetMsg(netmsg_t *b, char *buffer, int bufferlength);
void InitNetMsg(netmsg_t *b, void *buffer, int bufferlength);
unsigned char ReadByte(netmsg_t *b);
unsigned short ReadShort(netmsg_t *b);
unsigned int ReadLong(netmsg_t *b);
@ -897,11 +696,11 @@ void WriteLong(netmsg_t *b, unsigned int l);
void WriteFloat(netmsg_t *b, float f);
void WriteString2(netmsg_t *b, const char *str);
void WriteString(netmsg_t *b, const char *str);
void WriteData(netmsg_t *b, const char *data, int length);
void WriteData(netmsg_t *b, const void *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 Multicast(sv_t *tv, void *buffer, int length, int to, unsigned int playermask,int suitablefor);
void Broadcast(cluster_t *cluster, void *buffer, int length, int suitablefor);
void ParseMessage(sv_t *tv, void *buffer, int length, int to, int mask);
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);
@ -911,22 +710,26 @@ void Prox_SendInitialEnts(sv_t *qtv, oproxy_t *prox, netmsg_t *msg);
qboolean QTV_Connect(sv_t *qtv, char *serverurl);
void QTV_Shutdown(sv_t *qtv);
qboolean NET_StringToAddr (char *s, netadr_t *sadr, int defaultport);
void QTV_Printf(sv_t *qtv, char *format, ...);
void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean reliable);
void QW_PrintfToViewer(viewer_t *v, char *format, ...);
void QW_StuffcmdToViewer(viewer_t *v, char *format, ...);
void QW_StreamPrint(cluster_t *cluster, sv_t *server, viewer_t *allbut, char *message);
void QW_StreamStuffcmd(cluster_t *cluster, sv_t *server, char *fmt, ...);
void QTV_SayCommand(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *fullcommand); //execute a command from a view
void PM_PlayerMove (pmove_t *pmove);
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qboolean isclient);
void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...);
int Netchan_IsLocal (netadr_t adr);
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, netadr_t adr);
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, void *data, netadr_t adr);
qboolean Net_CompareAddress(netadr_t *s1, netadr_t *s2, int qp1, int qp2);
qboolean Netchan_Process (netchan_t *chan, netmsg_t *msg);
qboolean NQNetchan_Process(cluster_t *cluster, netchan_t *chan, netmsg_t *msg);
void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const unsigned char *data);
void Netchan_OutOfBand (cluster_t *cluster, SOCKET sock, netadr_t adr, int length, unsigned char *data);
void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const void *data);
void Netchan_OutOfBand (cluster_t *cluster, SOCKET sock, netadr_t adr, int length, void *data);
qboolean Netchan_CanPacket (netchan_t *chan);
int SendList(sv_t *qtv, int first, const filename_t *list, int svc, netmsg_t *msg);
@ -942,7 +745,7 @@ void BSP_SetupForPosition(bsp_t *bsp, float x, float y, float z);
const intermission_t *BSP_IntermissionSpot(bsp_t *bsp);
void QW_SetViewersServer(cluster_t *cluster, viewer_t *viewer, sv_t *sv);
unsigned short QCRC_Block (unsigned char *start, int count);
unsigned short QCRC_Block (void *start, int count);
unsigned short QCRC_Value(unsigned short crcvalue);
void WriteDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move);
void SendClientCommand(sv_t *qtv, char *fmt, ...);
@ -950,7 +753,6 @@ void QTV_Run(sv_t *qtv);
void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer);
void QW_SetMenu(viewer_t *v, int menunum);
char *Rcon_Command(cluster_t *cluster, sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qboolean localcommand);
char *COM_ParseToken (char *data, char *out, int outsize, const char *punctuation);
char *Info_ValueForKey (char *s, const char *key, char *buffer, int buffersize);
void Info_SetValueForStarKey (char *s, const char *key, const char *value, int maxsize);
@ -961,7 +763,7 @@ void Cluster_BuildAvailableDemoList(cluster_t *cluster);
void Sys_Printf(cluster_t *cluster, char *fmt, ...);
void Net_ProxySend(cluster_t *cluster, oproxy_t *prox, char *buffer, int length);
void Net_ProxySend(cluster_t *cluster, oproxy_t *prox, void *buffer, int length);
oproxy_t *Net_FileProxy(sv_t *qtv, char *filename);
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, char *password, qboolean force, qboolean autoclose, qboolean noduplicates, qboolean query);
SOCKET Net_MVDListen(int port);
@ -970,7 +772,7 @@ qboolean Net_StopFileProxy(sv_t *qtv);
void SV_FindProxies(SOCKET sock, cluster_t *cluster, sv_t *defaultqtv);
qboolean SV_ReadPendingProxy(cluster_t *cluster, oproxy_t *pend);
void SV_ForwardStream(sv_t *qtv, char *buffer, int length);
void SV_ForwardStream(sv_t *qtv, void *buffer, int length);
unsigned char *FS_ReadFile(char *gamedir, char *filename, unsigned int *size);

View File

@ -818,20 +818,20 @@ void NewNQClient(cluster_t *cluster, netadr_t *addr)
if (cluster->numviewers >= cluster->maxviewers && cluster->maxviewers)
{
buffer[4] = CCREP_REJECT;
strcpy(buffer+5, "Sorry, proxy is full.\n");
len = strlen(buffer+5)+5;
strcpy((char*)buffer+5, "Sorry, proxy is full.\n");
len = strlen((char*)buffer+5)+5;
}
/* else
{
buffer[4] = CCREP_REJECT;
strcpy(buffer+5, "NQ not supported yet\n");
len = strlen(buffer+5)+5;
strcpy((char*)buffer+5, "NQ not supported yet\n");
len = strlen((char*)buffer+5)+5;
}*/
else if (!(viewer = malloc(sizeof(viewer_t))))
{
buffer[4] = CCREP_REJECT;
strcpy(buffer+5, "Out of memory\n");
len = strlen(buffer+5)+5;
strcpy((char*)buffer+5, "Out of memory\n");
len = strlen((char*)buffer+5)+5;
}
else
{
@ -1124,7 +1124,7 @@ void QTV_Status(cluster_t *cluster, netadr_t *from)
{
sprintf(elem, "\\%i\\", sv->streamid);
WriteString2(&msg, elem);
WriteString2(&msg, sv->serveraddress);
WriteString2(&msg, (char*)sv->serveraddress);
sprintf(elem, " (%s)", sv->serveraddress);
WriteString2(&msg, elem);
}
@ -1885,7 +1885,6 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
short interp;
float lerp;
int track;
int runaway = 10;
int snapdist = 128; //in quake units
@ -1930,7 +1929,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
if (!v->commentator && track >= 0 && !v->backbuffered)
{
if (v->trackplayer != tv->trackplayer && tv->usequkeworldprotocols)
if (v->trackplayer != tv->trackplayer && tv->usequakeworldprotocols)
if (!tv->players[v->trackplayer].active && tv->players[tv->trackplayer].active)
{
QW_StuffcmdToViewer (v, "track %i\n", tv->trackplayer);
@ -2056,7 +2055,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
int newnum, oldnum;
frame_t *frompacket, *topacket;
topacket = &tv->frame[tv->netchan.incoming_sequence&(ENTITY_FRAMES-1)];
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
{
frompacket = &tv->frame[(topacket->oldframe)&(ENTITY_FRAMES-1)];
}
@ -2338,7 +2337,7 @@ void QTV_SayCommand(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *fullcomman
unsigned char *ip;
gethostname(buf, sizeof(buf)); //ask the operating system for the local dns name
NET_StringToAddr(buf, &addr, 0); //look that up
ip = (char*)&((struct sockaddr_in *)&addr)->sin_addr;
ip = (unsigned char*)&((struct sockaddr_in *)&addr)->sin_addr;
QW_PrintfToViewer(v, "[QuakeTV] %s | %i.%i.%i.%i\n", cluster->hostname, ip[0], ip[1], ip[2], ip[3]);
}
else if (!strcmp(command, "menu"))
@ -2678,7 +2677,7 @@ tuiadmin:
if (!strcmp(command, "join") || !strcmp(command, "connect"))
isjoin = true;
snprintf(buf, sizeof(buf), "udp:%s", args);
qtv = QTV_NewServerConnection(cluster, buf, "", false, true, !isjoin, false);
if (qtv)
@ -2689,6 +2688,8 @@ tuiadmin:
qtv->controller = v;
QW_PrintfToViewer(v, "Connected to %s\n", qtv->server);
}
else if (cluster->nouserconnects)
QW_PrintfToViewer(v, "you may not do that here\n");
else
QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", buf);
}
@ -2704,6 +2705,8 @@ tuiadmin:
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected to %s\n", qtv->server);
}
else if (cluster->nouserconnects)
QW_PrintfToViewer(v, "Ask an admin to connect first\n");
else
QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", buf);
}
@ -2741,7 +2744,7 @@ tuiadmin:
QW_PrintfToViewer(v, "Streaming from %s\n", qtv->server);
}
else
QW_PrintfToViewer(v, "Demo is not exist on proxy\n", buf);
QW_PrintfToViewer(v, "Demo does not exist on proxy\n", buf);
}
else if (!strcmp(command, "disconnect"))
{
@ -3039,7 +3042,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
message++;
*v->expectcommand = '\0';
if (qtv && qtv->usequkeworldprotocols && !noupwards)
if (qtv && qtv->usequakeworldprotocols && !noupwards)
{
if (qtv->controller == v || !*v->name)
{
@ -3063,6 +3066,8 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (cluster->notalking)
return;
SV_SayToUpstream(v->server, message);
for (ov = cluster->viewers; ov; ov = ov->next)
{
if (ov->server != v->server)
@ -3227,18 +3232,14 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
else if (!strncmp(buf, "setinfo", 5))
{
#define TOKENIZE_PUNCTUATION ""
#define MAX_ARGS 3
#define ARG_LEN 256
int i;
char arg[MAX_ARGS][ARG_LEN];
char *argptrs[MAX_ARGS];
char arg[3][ARG_LEN];
char *command = buf;
for (i = 0; i < MAX_ARGS; i++)
{
command = COM_ParseToken(command, arg[i], ARG_LEN, TOKENIZE_PUNCTUATION);
argptrs[i] = arg[i];
}
Info_SetValueForStarKey(v->userinfo, arg[1], arg[2], sizeof(v->userinfo));
@ -3672,18 +3673,14 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
else if (!strncmp(buf, "setinfo", 5))
{
#define TOKENIZE_PUNCTUATION ""
#define MAX_ARGS 3
#define ARG_LEN 256
int i;
char arg[MAX_ARGS][ARG_LEN];
char *argptrs[MAX_ARGS];
char arg[3][ARG_LEN];
char *command = buf;
for (i = 0; i < MAX_ARGS; i++)
for (i = 0; i < 3; i++)
{
command = COM_ParseToken(command, arg[i], ARG_LEN, TOKENIZE_PUNCTUATION);
argptrs[i] = arg[i];
}
Info_SetValueForStarKey(v->userinfo, arg[1], arg[2], sizeof(v->userinfo));
@ -4048,7 +4045,6 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer)
case MENU_MAIN:
{
int o = 8;
WriteString2(&m, "\n\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f\n");
while (viewer->menuop < 0)
viewer->menuop += MENU_MAIN_ITEMCOUNT;
@ -4406,7 +4402,9 @@ void SendViewerPackets(cluster_t *cluster, viewer_t *v)
v->maysend = (v->nextpacket < cluster->curtime);
}
if (!Netchan_CanPacket(&v->netchan))
{
return;
}
if (v->maysend) //don't send incompleate connection data.
{
// printf("maysend (%i, %i)\n", cluster->curtime, v->nextpacket);
@ -4438,6 +4436,7 @@ void SendViewerPackets(cluster_t *cluster, viewer_t *v)
WriteByte(&m, svc_centerprint);
WriteString(&m, v->server->status);
}
//printf("in %i, out %i, ", v->netchan.incoming_sequence, v->netchan.outgoing_sequence);
//if (v->netchan.incoming_sequence != v->netchan.outgoing_sequence)
//printf("%s: in %i, out %i\n", v->name, v->netchan.incoming_sequence, v->netchan.outgoing_sequence);
@ -4496,7 +4495,7 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
for (;;)
{
read = recvfrom(cluster->qwdsocket, buffer, sizeof(buffer), 0, (struct sockaddr*)from, &fromsize);
read = recvfrom(cluster->qwdsocket, buffer, sizeof(buffer), 0, (struct sockaddr*)from, (unsigned*)&fromsize);
if (read <= 5) //otherwise it's a runt or bad.
{

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#define RECONNECT_TIME (1000*30)
#define RECONNECT_TIME_DEMO (1000*5)
#define UDPRECONNECT_TIME (1000)
#define PINGSINTERVAL_TIME (1000*5)
#define UDPTIMEOUT_LENGTH (1000*20)
@ -98,9 +99,9 @@ qboolean NET_StringToAddr (char *s, netadr_t *sadr, int defaultport)
}
else
#endif
#ifdef IPPROTO_IPV6
#if 0//def IPPROTO_IPV6
if (getaddrinfo)
{
{//ipv6 method (can return ipv4 addresses too)
struct addrinfo *addrinfo, *pos;
struct addrinfo udp6hint;
int error;
@ -163,7 +164,7 @@ dblbreak:
}
else
#endif
{
{ //old fashioned method
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
((struct sockaddr_in *)sadr)->sin_port = htons(defaultport);
@ -511,12 +512,7 @@ qboolean DemoFilenameIsOkay(char *fname)
qboolean Net_ConnectToServer(sv_t *qtv)
{
char *at;
enum {
SRC_BAD,
SRC_DEMO,
SRC_UDP,
SRC_TCP
} type = SRC_BAD;
sourcetype_t type = SRC_BAD;
char *ip = qtv->server;
if (!strncmp(ip, "udp:", 4))
@ -548,31 +544,58 @@ qboolean Net_ConnectToServer(sv_t *qtv)
ip = at+1;
}
qtv->usequkeworldprotocols = false;
qtv->usequakeworldprotocols = false;
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
if (qtv->sourcetype == SRC_DEMO)
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME_DEMO; //wait half a minuite before trying to reconnect
else
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
qtv->sourcetype = type;
switch(type)
{
case SRC_DEMO:
qtv->sourcesock = INVALID_SOCKET;
if (DemoFilenameIsOkay(ip))
qtv->sourcefile = fopen(ip, "rb");
{
char fullname[512];
snprintf(fullname, sizeof(fullname), "%s%s", qtv->cluster->demodir, ip);
qtv->sourcefile = fopen(fullname, "rb");
}
else
qtv->sourcefile = NULL;
if (qtv->sourcefile)
{
char smallbuffer[17];
fseek(qtv->sourcefile, 0, SEEK_END);
qtv->filelength = ftell(qtv->sourcefile);
//attempt to detect the end of the file
fseek(qtv->sourcefile, -sizeof(smallbuffer), SEEK_CUR);
fread(smallbuffer, 1, 17, qtv->sourcefile);
//0 is the time
if (smallbuffer[1] == dem_all || smallbuffer[1] == dem_read) //mvdsv changed it to read...
{
//2,3,4,5 are the length
if (smallbuffer[6] == svc_disconnect)
{
if (!strcmp(smallbuffer+7, "EndOfDemo"))
{
qtv->filelength -= 17;
}
}
}
fseek(qtv->sourcefile, 0, SEEK_SET);
return true;
}
Sys_Printf(qtv->cluster, "Unable to open file %s\n", ip+5);
Sys_Printf(qtv->cluster, "Unable to open file %s\n", ip);
return false;
case SRC_UDP:
qtv->usequkeworldprotocols = true;
qtv->usequakeworldprotocols = true;
return Net_ConnectToUDPServer(qtv, ip);
case SRC_TCP:
@ -586,7 +609,7 @@ qboolean Net_ConnectToServer(sv_t *qtv)
void Net_QueueUpstream(sv_t *qtv, int size, char *buffer)
{
if (qtv->usequkeworldprotocols)
if (qtv->usequakeworldprotocols)
return;
if (qtv->upstreambuffersize + size > sizeof(qtv->upstreambuffer))
@ -599,7 +622,7 @@ void Net_QueueUpstream(sv_t *qtv, int size, char *buffer)
qtv->upstreambuffersize += size;
}
qboolean Net_WriteUpStream(sv_t *qtv)
qboolean Net_WriteUpstream(sv_t *qtv)
{
int len;
@ -629,7 +652,48 @@ qboolean Net_WriteUpStream(sv_t *qtv)
return true;
}
int SV_ConsistantMVDData(unsigned char *buffer, int remaining)
void SV_SendUpstream(sv_t *qtv, netmsg_t *nm)
{
char size[2];
size[0] = (nm->cursize&0x00ff)>>0;
size[1] = (nm->cursize&0xff00)>>8;
Net_QueueUpstream(qtv, 2, size);
Net_QueueUpstream(qtv, nm->cursize, nm->data);
Net_WriteUpstream(qtv); //try and flush it
}
int SV_SayToUpstream(sv_t *qtv, char *message)
{
char buffer[1024];
netmsg_t nm;
if (!qtv->upstreamacceptschat)
{
Sys_Printf(qtv->cluster, "not forwarding say\n");
return 0;
}
InitNetMsg(&nm, buffer, sizeof(buffer));
WriteByte(&nm, qtv_clc_stringcmd);
WriteString2(&nm, "say ");
WriteString(&nm, message);
SV_SendUpstream(qtv, &nm);
return 1;
}
void SV_SayToViewers(sv_t *qtv, char *message)
{
viewer_t *v;
Fwd_SayToDownstream(qtv, message);
#warning Send to viewers here too
}
//This function 1: parses the 'don't delay' packets in the stream
// 2: returns the length of continuous data (that is, whole-packet bytes that have not been truncated by the networking layer)
// this means we know that the client proxies have valid data, at least from our side.
int SV_EarlyParse(sv_t *qtv, unsigned char *buffer, int remaining)
{
int lengthofs;
int length;
@ -644,8 +708,8 @@ int SV_ConsistantMVDData(unsigned char *buffer, int remaining)
switch (buffer[1]&dem_mask)
{
case dem_set:
length = 10;
goto gottotallength;
lengthofs = 0; //to silence gcc, nothing more
break;
case dem_multiple:
lengthofs = 6;
break;
@ -654,17 +718,27 @@ int SV_ConsistantMVDData(unsigned char *buffer, int remaining)
break;
}
if (lengthofs+4 > remaining)
return available;
if (lengthofs > 0)
{
if (lengthofs+4 > remaining)
return available;
length = (buffer[lengthofs]<<0) + (buffer[lengthofs+1]<<8) + (buffer[lengthofs+2]<<16) + (buffer[lengthofs+3]<<24);
length = (buffer[lengthofs]<<0) + (buffer[lengthofs+1]<<8) + (buffer[lengthofs+2]<<16) + (buffer[lengthofs+3]<<24);
length += lengthofs+4;
if (length > 1500)
printf("Probably corrupt mvd (length %i)\n", length);
}
else
length = 10;
length += lengthofs+4;
if (length > 1400)
printf("Corrupt mvd\n");
gottotallength:
if (remaining < length)
return available;
if ((buffer[1]&dem_mask) == dem_all && (buffer[1] & ~dem_mask) && qtv->sourcetype != SRC_DEMO) //dem_qtvdata
{
ParseMessage(qtv, buffer+lengthofs+4, length - (lengthofs+4), buffer[1], 0xffffffff);
}
remaining -= length;
available += length;
@ -676,7 +750,7 @@ qboolean Net_ReadStream(sv_t *qtv)
{
int maxreadable;
int read;
char *buffer;
void *buffer;
int err;
maxreadable = MAX_PROXY_BUFFER - qtv->buffersize;
@ -690,13 +764,21 @@ qboolean Net_ReadStream(sv_t *qtv)
maxreadable = PREFERED_PROXY_BUFFER-qtv->buffersize;
if (maxreadable<=0)
return true;
//reuse read a little...
read = ftell(qtv->sourcefile);
if (read+maxreadable > qtv->filelength)
maxreadable = qtv->filelength-read; //clamp to the end of the file
//even if that 'end' is before the svc_disconnect
read = fread(buffer, 1, maxreadable, qtv->sourcefile);
}
else
{
read = sizeof(err);
unsigned int errsize;
errsize = sizeof(err);
err = 0;
getsockopt(qtv->sourcesock, SOL_SOCKET, SO_ERROR, (char*)&err, &read);
getsockopt(qtv->sourcesock, SOL_SOCKET, SO_ERROR, (char*)&err, &errsize);
if (err == ECONNREFUSED)
{
Sys_Printf(qtv->cluster, "Error: server %s refused connection\n", qtv->server);
@ -714,7 +796,7 @@ qboolean Net_ReadStream(sv_t *qtv)
if (!qtv->cluster->lateforward && !qtv->parsingqtvheader) //qtv header being the auth part of the connection rather than the stream
{
int forwardable;
forwardable = SV_ConsistantMVDData(qtv->buffer+qtv->forwardpoint, qtv->buffersize - qtv->forwardpoint);
forwardable = SV_EarlyParse(qtv, qtv->buffer+qtv->forwardpoint, qtv->buffersize - qtv->forwardpoint);
if (forwardable > 0)
{
SV_ForwardStream(qtv, qtv->buffer+qtv->forwardpoint, forwardable);
@ -752,7 +834,7 @@ qboolean Net_ReadStream(sv_t *qtv)
return true;
}
#define BUFFERTIME 10 //secords for arificial delay, so we can buffer things properly.
#define BUFFERTIME 10 //secords for artificial delay, so we can buffer things properly.
unsigned int Sys_Milliseconds(void)
{
@ -777,10 +859,12 @@ unsigned int Sys_Milliseconds(void)
return timeGetTime();
#else
//assume every other system follows standards.
unsigned int t;
struct timeval tv;
gettimeofday(&tv, NULL);
return ((unsigned)tv.tv_sec)*1000 + (((unsigned)tv.tv_usec)/1000);
t = ((unsigned int)tv.tv_sec)*1000 + (((unsigned int)tv.tv_usec)/1000);
return t;
#endif
}
/*
@ -921,7 +1005,7 @@ qboolean QTV_Connect(sv_t *qtv, char *serverurl)
memcpy(qtv->server, serverurl, sizeof(qtv->server)-1);
if (qtv->disconnectwhennooneiswatching)
if (qtv->disconnectwhennooneiswatching == 2)
{ //added because of paranoia rather than need. Should never occur.
printf("bug: autoclose==2\n");
return false;
@ -998,7 +1082,7 @@ void QTV_Shutdown(sv_t *qtv)
{
QW_SetViewersServer(qtv->cluster, v, NULL);
QW_SetMenu(v, MENU_NONE);
QTV_Say(cluster, v->server, v, ".menu", false);
QTV_SayCommand(cluster, v->server, v, "menu");
QW_PrintfToViewer(v, "Stream %s is closing\n", qtv->server);
}
}
@ -1076,7 +1160,7 @@ void ChooseFavoriteTrack(sv_t *tv)
SendClientCommand (tv, "ptrack %i\n", best);
tv->trackplayer = best;
if (tv->usequkeworldprotocols)
if (tv->usequakeworldprotocols)
QW_StreamStuffcmd(tv->cluster, tv, "track %i\n", best);
}
}
@ -1122,7 +1206,7 @@ static const unsigned char chktbl[1024] = {
};
unsigned char COM_BlockSequenceCRCByte (unsigned char *base, int length, int sequence)
unsigned char COM_BlockSequenceCRCByte (void *base, int length, int sequence)
{
unsigned short crc;
const unsigned char *p;
@ -1165,7 +1249,7 @@ void QTV_ParseQWStream(sv_t *qtv)
{
char buffer[1500];
netadr_t from;
int fromlen;
unsigned int fromlen;
int readlen;
netmsg_t msg;
fromlen = sizeof(from); //bug: this won't work on (free)bsd
@ -1386,7 +1470,7 @@ void QTV_Run(sv_t *qtv)
if (qtv->usequkeworldprotocols)
if (qtv->sourcetype == SRC_UDP)
{
qtv->simtime += qtv->curtime - oldcurtime;
@ -1560,12 +1644,13 @@ void QTV_Run(sv_t *qtv)
//obviously, we need to keep reading the stream to keep things smooth
}
Net_WriteUpStream(qtv);
Net_WriteUpstream(qtv);
}
if (qtv->parsingqtvheader)
{
float svversion;
int length;
char *start;
char *nl;
@ -1584,16 +1669,17 @@ void QTV_Run(sv_t *qtv)
length = qtv->buffersize;
if (length > 6)
length = 6;
if (strncmp(qtv->buffer, "QTVSV ", length))
if (ustrncmp(qtv->buffer, "QTVSV ", length))
{
Sys_Printf(qtv->cluster, "Server is not a QTV server (or is incompatable)\n");
printf("%i, %s\n", qtv->buffersize, qtv->buffer);
qtv->drop = true;
return;
}
if (length < 6)
return; //not ready yet
end = qtv->buffer + qtv->buffersize - 1;
for (nl = qtv->buffer; nl < end; nl++)
end = (char*)qtv->buffer + qtv->buffersize - 1;
for (nl = (char*)qtv->buffer; nl < end; nl++)
{
if (nl[0] == '\n' && nl[1] == '\n')
break;
@ -1603,17 +1689,22 @@ void QTV_Run(sv_t *qtv)
//we now have a complete packet.
if (atoi(qtv->buffer + 6) != 1)
svversion = atof((char*)qtv->buffer + 6);
if ((int)svversion != 1)
{
Sys_Printf(qtv->cluster, "QTV server doesn't support a compatable protocol version (returned %i)\n", atoi(qtv->buffer + 6));
Sys_Printf(qtv->cluster, "QTV server doesn't support a compatable protocol version (returned %i)\n", atoi((char*)qtv->buffer + 6));
qtv->drop = true;
return;
}
qtv->upstreamacceptschat = svversion>=1.1;
qtv->upstreamacceptsdownload = svversion>=1.1;
length = (nl - (char*)qtv->buffer) + 2;
end = nl;
nl[1] = '\0';
start = strchr(qtv->buffer, '\n')+1;
start = strchr((char*)qtv->buffer, '\n')+1;
while((nl = strchr(start, '\n')))
{
@ -1710,7 +1801,7 @@ void QTV_Run(sv_t *qtv)
if (qtv->serverquery)
{
Sys_Printf(qtv->cluster, "End of list\n", colon);
Sys_Printf(qtv->cluster, "End of list\n");
qtv->drop = true;
qtv->buffersize = 0;
return;
@ -1722,14 +1813,14 @@ void QTV_Run(sv_t *qtv)
}
else if (qtv->parsingqtvheader)
{
Sys_Printf(qtv->cluster, "QTV server sent no begin command - assuming incompatable\n\n", colon);
Sys_Printf(qtv->cluster, "QTV server sent no begin command - assuming incompatable\n\n");
qtv->drop = true;
qtv->buffersize = 0;
return;
}
qtv->parsetime = Sys_Milliseconds() + BUFFERTIME*1000;
if (!qtv->usequkeworldprotocols)
if (!qtv->usequakeworldprotocols)
Sys_Printf(qtv->cluster, "Connection established, buffering for %i seconds\n", BUFFERTIME);
SV_ForwardStream(qtv, qtv->buffer, qtv->forwardpoint);
@ -1737,7 +1828,6 @@ void QTV_Run(sv_t *qtv)
QTV_CollectCommentry(qtv);
while (qtv->curtime >= qtv->parsetime)
{
if (qtv->buffersize < 2)
@ -1746,7 +1836,7 @@ void QTV_Run(sv_t *qtv)
{
qtv->parsetime = qtv->curtime + 2*1000; //add two seconds
if (qtv->sourcefile || qtv->sourcesock != INVALID_SOCKET)
Sys_Printf(qtv->cluster, "Not enough buffered\n");
QTV_Printf(qtv, "Not enough buffered\n");
}
break;
}
@ -1761,7 +1851,7 @@ void QTV_Run(sv_t *qtv)
{ //not enough stuff to play.
qtv->parsetime = qtv->curtime + 2*1000; //add two seconds
if (qtv->sourcefile || qtv->sourcesock != INVALID_SOCKET)
Sys_Printf(qtv->cluster, "Not enough buffered\n");
QTV_Printf(qtv, "Not enough buffered\n");
continue;
}
qtv->parsetime += buffer[0]; //well this was pointless
@ -1787,17 +1877,17 @@ void QTV_Run(sv_t *qtv)
if (qtv->buffersize < lengthofs+4)
{ //the size parameter doesn't fit.
if (qtv->sourcefile || qtv->sourcesock != INVALID_SOCKET)
Sys_Printf(qtv->cluster, "Not enough buffered\n");
QTV_Printf(qtv, "Not enough buffered\n");
qtv->parsetime = qtv->curtime + 2*1000; //add two seconds
break;
}
length = (buffer[lengthofs]<<0) + (buffer[lengthofs+1]<<8) + (buffer[lengthofs+2]<<16) + (buffer[lengthofs+3]<<24);
if (length > 1450)
{ //FIXME: THIS SHOULDN'T HAPPEN!
if (length > 1500)
{ //THIS SHOULDN'T HAPPEN!
//Blame the upstream proxy!
Sys_Printf(qtv->cluster, "Warning: corrupt input packet (%i) too big! Flushing and reconnecting!\n", length);
QTV_Printf(qtv, "Warning: corrupt input packet (%i bytes) too big! Flushing and reconnecting!\n", length);
if (qtv->sourcefile)
{
fclose(qtv->sourcefile);
@ -1815,12 +1905,21 @@ void QTV_Run(sv_t *qtv)
if (length+lengthofs+4 > qtv->buffersize)
{
if (qtv->sourcefile || qtv->sourcesock != INVALID_SOCKET)
Sys_Printf(qtv->cluster, "Not enough buffered\n");
QTV_Printf(qtv, "Not enough buffered\n");
qtv->parsetime = qtv->curtime + 2*1000; //add two seconds
break; //can't parse it yet.
}
qtv->nextpackettime = qtv->parsetime+buffer[0];
// if (qtv->sourcesock != INVALID_SOCKET)
// {
// QTV_Printf(qtv, "Forcing demo speed to play at 100% speed\n");
// qtv->parsespeed = 1000; //no speeding up/slowing down routed demos
// }
packettime = buffer[0];
if (qtv->parsespeed>0)
packettime = ((1000*packettime) / qtv->parsespeed);
qtv->nextpackettime = qtv->parsetime + packettime;
if (qtv->nextpackettime < qtv->curtime)
{
@ -1833,9 +1932,13 @@ void QTV_Run(sv_t *qtv)
case dem_stats:
ParseMessage(qtv, buffer+lengthofs+4, length, qtv->buffer[1]&dem_mask, 1<<(qtv->buffer[1]>>3));
break;
case dem_read:
case dem_all:
ParseMessage(qtv, buffer+lengthofs+4, length, qtv->buffer[1]&dem_mask, 0xffffffff);
if (qtv->buffer[1] & ~dem_mask) //dem_qtvdata
if (qtv->sourcetype != SRC_DEMO)
break;
//fallthrough
case dem_read:
ParseMessage(qtv, buffer+lengthofs+4, length, qtv->buffer[1], 0xffffffff);
break;
default:
Sys_Printf(qtv->cluster, "Message type %i\n", qtv->buffer[1]&dem_mask);
@ -1846,7 +1949,6 @@ void QTV_Run(sv_t *qtv)
qtv->oldpackettime = qtv->curtime;
packettime = buffer[0];
if (qtv->buffersize)
{ //svc_disconnect can flush our input buffer (to prevent the EndOfDemo part from interfering)
@ -1906,6 +2008,7 @@ sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, char *password,
qtv->parsingconnectiondata = true;
qtv->serverquery = query;
qtv->silentstream = true;
qtv->parsespeed = 1000;
qtv->streamid = ++cluster->nextstreamid;