mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 14:42:13 +00:00
Gets past map checks... but times out too easily in linux :(
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1981 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
5e2c8dac61
commit
2d86a6140b
9 changed files with 901 additions and 159 deletions
|
@ -4,7 +4,7 @@ STRIP=strip
|
||||||
|
|
||||||
STRIPFLAGS=--strip-unneeded --remove-section=.comment
|
STRIPFLAGS=--strip-unneeded --remove-section=.comment
|
||||||
|
|
||||||
OBJS = netchan.o parse.o qw.o source.o bsp.o rcon.o
|
OBJS = netchan.o parse.o qw.o source.o bsp.o rcon.o mdfour.o
|
||||||
|
|
||||||
qtv: $(OBJS) qtv.h
|
qtv: $(OBJS) qtv.h
|
||||||
$(CC) $(CFLAGS) $(OBJS) -o $@.db -lm $(LDFLAGS)
|
$(CC) $(CFLAGS) $(OBJS) -o $@.db -lm $(LDFLAGS)
|
||||||
|
|
72
fteqtv/bsp.c
72
fteqtv/bsp.c
|
@ -28,6 +28,8 @@ typedef struct {
|
||||||
int child[2];
|
int child[2];
|
||||||
} node_t;
|
} node_t;
|
||||||
struct bsp_s {
|
struct bsp_s {
|
||||||
|
unsigned int fullchecksum;
|
||||||
|
unsigned int visedchecksum;
|
||||||
node_t *nodes;
|
node_t *nodes;
|
||||||
unsigned char *pvslump;
|
unsigned char *pvslump;
|
||||||
unsigned char **pvsofs;
|
unsigned char **pvsofs;
|
||||||
|
@ -69,6 +71,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
int fileofs, filelen;
|
int fileofs, filelen;
|
||||||
} lump_t;
|
} lump_t;
|
||||||
|
#define LUMP_ENTITIES 0
|
||||||
#define LUMP_PLANES 1
|
#define LUMP_PLANES 1
|
||||||
#define LUMP_VISIBILITY 4
|
#define LUMP_VISIBILITY 4
|
||||||
#define LUMP_NODES 5
|
#define LUMP_NODES 5
|
||||||
|
@ -186,7 +189,8 @@ unsigned char *ReadFile_WINDOWSSUCKS(char *gamedir, char *filename, int *size)
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
data = malloc(*size);
|
data = malloc(*size);
|
||||||
fread(data, 1, *size, f);
|
if (data)
|
||||||
|
fread(data, 1, *size, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -204,6 +208,7 @@ bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
|
||||||
|
|
||||||
int numnodes, i;
|
int numnodes, i;
|
||||||
int numleafs;
|
int numleafs;
|
||||||
|
unsigned int chksum;
|
||||||
|
|
||||||
bsp_t *bsp;
|
bsp_t *bsp;
|
||||||
|
|
||||||
|
@ -237,29 +242,45 @@ bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
|
||||||
numleafs = header->lumps[LUMP_LEAFS].filelen/sizeof(dleaf_t);
|
numleafs = header->lumps[LUMP_LEAFS].filelen/sizeof(dleaf_t);
|
||||||
|
|
||||||
bsp = malloc(sizeof(bsp_t) + sizeof(node_t)*numnodes + header->lumps[LUMP_VISIBILITY].filelen + sizeof(unsigned char *)*numleafs);
|
bsp = malloc(sizeof(bsp_t) + sizeof(node_t)*numnodes + header->lumps[LUMP_VISIBILITY].filelen + sizeof(unsigned char *)*numleafs);
|
||||||
bsp->nodes = (node_t*)(bsp+1);
|
if (bsp)
|
||||||
bsp->pvsofs = (unsigned char**)(bsp->nodes+numnodes);
|
|
||||||
bsp->pvslump = (unsigned char*)(bsp->pvsofs+numleafs);
|
|
||||||
|
|
||||||
bsp->pvsbytecount = (numleafs+7)/8;
|
|
||||||
|
|
||||||
for (i = 0; i < numnodes; i++)
|
|
||||||
{
|
{
|
||||||
bsp->nodes[i].child[0] = nodes[i].children[0];
|
bsp->fullchecksum = 0;
|
||||||
bsp->nodes[i].child[1] = nodes[i].children[1];
|
bsp->visedchecksum = 0;
|
||||||
bsp->nodes[i].planedist = planes[nodes[i].planenum].dist;
|
for (i = 0; i < HEADER_LUMPS; i++)
|
||||||
bsp->nodes[i].planen[0] = planes[nodes[i].planenum].normal[0];
|
{
|
||||||
bsp->nodes[i].planen[1] = planes[nodes[i].planenum].normal[1];
|
if (i == LUMP_ENTITIES)
|
||||||
bsp->nodes[i].planen[2] = planes[nodes[i].planenum].normal[2];
|
continue; //entities never appear in any checksums
|
||||||
}
|
|
||||||
memcpy(bsp->pvslump, data+header->lumps[LUMP_VISIBILITY].fileofs, header->lumps[LUMP_VISIBILITY].filelen);
|
|
||||||
|
|
||||||
for (i = 0; i < numleafs; i++)
|
chksum = Com_BlockChecksum(data + header->lumps[i].fileofs, header->lumps[i].filelen);
|
||||||
{
|
bsp->fullchecksum ^= chksum;
|
||||||
if (leaf[i].visofs < 0)
|
if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
|
||||||
bsp->pvsofs[i] = NULL;
|
continue;
|
||||||
else
|
bsp->visedchecksum ^= chksum;
|
||||||
bsp->pvsofs[i] = bsp->pvslump+leaf[i].visofs;
|
}
|
||||||
|
bsp->nodes = (node_t*)(bsp+1);
|
||||||
|
bsp->pvsofs = (unsigned char**)(bsp->nodes+numnodes);
|
||||||
|
bsp->pvslump = (unsigned char*)(bsp->pvsofs+numleafs);
|
||||||
|
|
||||||
|
bsp->pvsbytecount = (numleafs+7)/8;
|
||||||
|
|
||||||
|
for (i = 0; i < numnodes; i++)
|
||||||
|
{
|
||||||
|
bsp->nodes[i].child[0] = nodes[i].children[0];
|
||||||
|
bsp->nodes[i].child[1] = nodes[i].children[1];
|
||||||
|
bsp->nodes[i].planedist = planes[nodes[i].planenum].dist;
|
||||||
|
bsp->nodes[i].planen[0] = planes[nodes[i].planenum].normal[0];
|
||||||
|
bsp->nodes[i].planen[1] = planes[nodes[i].planenum].normal[1];
|
||||||
|
bsp->nodes[i].planen[2] = planes[nodes[i].planenum].normal[2];
|
||||||
|
}
|
||||||
|
memcpy(bsp->pvslump, data+header->lumps[LUMP_VISIBILITY].fileofs, header->lumps[LUMP_VISIBILITY].filelen);
|
||||||
|
|
||||||
|
for (i = 0; i < numleafs; i++)
|
||||||
|
{
|
||||||
|
if (leaf[i].visofs < 0)
|
||||||
|
bsp->pvsofs[i] = NULL;
|
||||||
|
else
|
||||||
|
bsp->pvsofs[i] = bsp->pvslump+leaf[i].visofs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -314,6 +335,13 @@ int BSP_SphereLeafNums_r(bsp_t *bsp, int first, int maxleafs, unsigned short *li
|
||||||
return numleafs;
|
return numleafs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int BSP_Checksum(bsp_t *bsp)
|
||||||
|
{
|
||||||
|
if (!bsp)
|
||||||
|
return 0;
|
||||||
|
return bsp->visedchecksum;
|
||||||
|
}
|
||||||
|
|
||||||
int BSP_SphereLeafNums(bsp_t *bsp, int maxleafs, unsigned short *list, float x, float y, float z, float radius)
|
int BSP_SphereLeafNums(bsp_t *bsp, int maxleafs, unsigned short *list, float x, float y, float z, float radius)
|
||||||
{
|
{
|
||||||
float pos[3];
|
float pos[3];
|
||||||
|
|
254
fteqtv/mdfour.c
Normal file
254
fteqtv/mdfour.c
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
mdfour.c
|
||||||
|
|
||||||
|
An implementation of MD4 designed for use in the samba SMB
|
||||||
|
authentication protocol
|
||||||
|
|
||||||
|
Copyright (C) 1997-1998 Andrew Tridgell
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h> /* XoXus: needed for memset call */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _MDFOUR_H
|
||||||
|
#define _MDFOUR_H
|
||||||
|
|
||||||
|
#ifndef int32
|
||||||
|
#define int32 int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SIZEOF_INT > 4
|
||||||
|
#define LARGE_INT32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef uint32
|
||||||
|
#define uint32 unsigned int32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mdfour {
|
||||||
|
uint32 A, B, C, D;
|
||||||
|
uint32 totalN;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mdfour_begin(struct mdfour *md); // old: MD4Init
|
||||||
|
void mdfour_update(struct mdfour *md, unsigned char *in, int n); //old: MD4Update
|
||||||
|
void mdfour_result(struct mdfour *md, unsigned char *out); // old: MD4Final
|
||||||
|
void mdfour(unsigned char *out, unsigned char *in, int n);
|
||||||
|
|
||||||
|
#endif // _MDFOUR_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: This code makes no attempt to be fast!
|
||||||
|
|
||||||
|
It assumes that a int is at least 32 bits long
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct mdfour *m;
|
||||||
|
|
||||||
|
#define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z)))
|
||||||
|
#define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)))
|
||||||
|
#define H(X,Y,Z) ((X)^(Y)^(Z))
|
||||||
|
#ifdef LARGE_INT32
|
||||||
|
#define lshift(x,s) ((((x)<<(s))&0xFFFFFFFF) | (((x)>>(32-(s)))&0xFFFFFFFF))
|
||||||
|
#else
|
||||||
|
#define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s))))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
|
||||||
|
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
|
||||||
|
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
|
||||||
|
|
||||||
|
/* this applies md4 to 64 byte chunks */
|
||||||
|
static void mdfour64(uint32 *M)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
uint32 AA, BB, CC, DD;
|
||||||
|
uint32 X[16];
|
||||||
|
uint32 A,B,C,D;
|
||||||
|
|
||||||
|
for (j=0;j<16;j++)
|
||||||
|
X[j] = M[j];
|
||||||
|
|
||||||
|
A = m->A; B = m->B; C = m->C; D = m->D;
|
||||||
|
AA = A; BB = B; CC = C; DD = D;
|
||||||
|
|
||||||
|
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
|
||||||
|
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
|
||||||
|
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
|
||||||
|
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
|
||||||
|
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
|
||||||
|
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
|
||||||
|
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
|
||||||
|
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
|
||||||
|
|
||||||
|
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
|
||||||
|
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
|
||||||
|
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
|
||||||
|
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
|
||||||
|
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
|
||||||
|
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
|
||||||
|
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
|
||||||
|
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
|
||||||
|
|
||||||
|
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
|
||||||
|
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
|
||||||
|
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
|
||||||
|
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
|
||||||
|
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
|
||||||
|
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
|
||||||
|
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
|
||||||
|
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
|
||||||
|
|
||||||
|
A += AA; B += BB; C += CC; D += DD;
|
||||||
|
|
||||||
|
#ifdef LARGE_INT32
|
||||||
|
A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
|
||||||
|
C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (j=0;j<16;j++)
|
||||||
|
X[j] = 0;
|
||||||
|
|
||||||
|
m->A = A; m->B = B; m->C = C; m->D = D;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy64(uint32 *M, unsigned char *in)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<16;i++)
|
||||||
|
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
|
||||||
|
(in[i*4+1]<<8) | (in[i*4+0]<<0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy4(unsigned char *out,uint32 x)
|
||||||
|
{
|
||||||
|
out[0] = x&0xFF;
|
||||||
|
out[1] = (x>>8)&0xFF;
|
||||||
|
out[2] = (x>>16)&0xFF;
|
||||||
|
out[3] = (x>>24)&0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mdfour_begin(struct mdfour *md)
|
||||||
|
{
|
||||||
|
md->A = 0x67452301;
|
||||||
|
md->B = 0xefcdab89;
|
||||||
|
md->C = 0x98badcfe;
|
||||||
|
md->D = 0x10325476;
|
||||||
|
md->totalN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void mdfour_tail(unsigned char *in, int n)
|
||||||
|
{
|
||||||
|
unsigned char buf[128];
|
||||||
|
uint32 M[16];
|
||||||
|
uint32 b;
|
||||||
|
|
||||||
|
m->totalN += n;
|
||||||
|
|
||||||
|
b = m->totalN * 8;
|
||||||
|
|
||||||
|
memset(buf, 0, 128);
|
||||||
|
if (n) memcpy(buf, in, n);
|
||||||
|
buf[n] = 0x80;
|
||||||
|
|
||||||
|
if (n <= 55) {
|
||||||
|
copy4(buf+56, b);
|
||||||
|
copy64(M, buf);
|
||||||
|
mdfour64(M);
|
||||||
|
} else {
|
||||||
|
copy4(buf+120, b);
|
||||||
|
copy64(M, buf);
|
||||||
|
mdfour64(M);
|
||||||
|
copy64(M, buf+64);
|
||||||
|
mdfour64(M);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mdfour_update(struct mdfour *md, unsigned char *in, int n)
|
||||||
|
{
|
||||||
|
uint32 M[16];
|
||||||
|
|
||||||
|
m = md;
|
||||||
|
|
||||||
|
// if (n == 0) mdfour_tail(in, n); //Spike: This is where the bug was.
|
||||||
|
|
||||||
|
while (n >= 64) {
|
||||||
|
copy64(M, in);
|
||||||
|
mdfour64(M);
|
||||||
|
in += 64;
|
||||||
|
n -= 64;
|
||||||
|
m->totalN += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdfour_tail(in, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mdfour_result(struct mdfour *md, unsigned char *out)
|
||||||
|
{
|
||||||
|
m = md;
|
||||||
|
|
||||||
|
copy4(out, m->A);
|
||||||
|
copy4(out+4, m->B);
|
||||||
|
copy4(out+8, m->C);
|
||||||
|
copy4(out+12, m->D);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mdfour(unsigned char *out, unsigned char *in, int n)
|
||||||
|
{
|
||||||
|
struct mdfour md;
|
||||||
|
mdfour_begin(&md);
|
||||||
|
mdfour_update(&md, in, n);
|
||||||
|
mdfour_result(&md, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////
|
||||||
|
// MD4-based checksum utility functions
|
||||||
|
//
|
||||||
|
// Copyright (C) 2000 Jeff Teunissen <d2deek@pmail.net>
|
||||||
|
//
|
||||||
|
// Author: Jeff Teunissen <d2deek@pmail.net>
|
||||||
|
// Date: 01 Jan 2000
|
||||||
|
|
||||||
|
unsigned Com_BlockChecksum (void *buffer, int length)
|
||||||
|
{
|
||||||
|
int digest[4];
|
||||||
|
unsigned val;
|
||||||
|
|
||||||
|
mdfour ( (unsigned char *) digest, (unsigned char *) buffer, length );
|
||||||
|
|
||||||
|
val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf)
|
||||||
|
{
|
||||||
|
mdfour ( outbuf, (unsigned char *) buffer, len );
|
||||||
|
}
|
|
@ -39,8 +39,7 @@ int Netchan_IsLocal (netadr_t adr)
|
||||||
{
|
{
|
||||||
struct sockaddr_in *sadr = (struct sockaddr_in *)adr;
|
struct sockaddr_in *sadr = (struct sockaddr_in *)adr;
|
||||||
unsigned char *bytes;
|
unsigned char *bytes;
|
||||||
bytes = (char *)&sadr->sin_addr;
|
bytes = (unsigned char *)&sadr->sin_addr;
|
||||||
|
|
||||||
if (bytes[0] == 127 &&
|
if (bytes[0] == 127 &&
|
||||||
bytes[1] == 0 &&
|
bytes[1] == 0 &&
|
||||||
bytes[2] == 0 &&
|
bytes[2] == 0 &&
|
||||||
|
@ -175,13 +174,14 @@ Netchan_Setup
|
||||||
called to open a channel to a remote system
|
called to open a channel to a remote system
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport)
|
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qboolean isclient)
|
||||||
{
|
{
|
||||||
memset (chan, 0, sizeof(*chan));
|
memset (chan, 0, sizeof(*chan));
|
||||||
|
|
||||||
chan->sock = sock;
|
chan->sock = sock;
|
||||||
memcpy(&chan->remote_address, adr, sizeof(netadr_t));
|
memcpy(&chan->remote_address, adr, sizeof(netadr_t));
|
||||||
chan->qport = qport;
|
chan->qport = qport;
|
||||||
|
chan->isclient = isclient;
|
||||||
|
|
||||||
chan->last_received = curtime;
|
chan->last_received = curtime;
|
||||||
|
|
||||||
|
@ -284,8 +284,8 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const un
|
||||||
WriteLong (&send, w2);
|
WriteLong (&send, w2);
|
||||||
|
|
||||||
// send the qport if we are a client
|
// send the qport if we are a client
|
||||||
// if (chan->sock == NS_CLIENT)
|
if (chan->isclient)
|
||||||
// MSG_WriteShort (&send, chan->qport);
|
WriteShort (&send, chan->qport);
|
||||||
|
|
||||||
// copy the reliable message to the packet first
|
// copy the reliable message to the packet first
|
||||||
if (send_reliable)
|
if (send_reliable)
|
||||||
|
@ -343,7 +343,7 @@ qboolean Netchan_Process (netchan_t *chan, netmsg_t *msg)
|
||||||
sequence_ack = ReadLong (msg);
|
sequence_ack = ReadLong (msg);
|
||||||
|
|
||||||
// read the qport if we are a server
|
// read the qport if we are a server
|
||||||
// if (chan->sock == NS_SERVER)
|
if (!chan->isclient)
|
||||||
ReadShort (msg);
|
ReadShort (msg);
|
||||||
|
|
||||||
reliable_message = sequence >> 31;
|
reliable_message = sequence >> 31;
|
||||||
|
|
187
fteqtv/parse.c
187
fteqtv/parse.c
|
@ -216,11 +216,17 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
||||||
|
|
||||||
tv->parsingconnectiondata = true;
|
tv->parsingconnectiondata = true;
|
||||||
|
|
||||||
ReadLong(m); //we don't care about server's servercount, it's all reliable data anyway.
|
tv->clservercount = ReadLong(m); //we don't care about server's servercount, it's all reliable data anyway.
|
||||||
|
|
||||||
ReadString(m, tv->gamedir, sizeof(tv->gamedir));
|
ReadString(m, tv->gamedir, sizeof(tv->gamedir));
|
||||||
|
|
||||||
/*tv->servertime =*/ ReadFloat(m);
|
if (tv->usequkeworldprotocols)
|
||||||
|
tv->thisplayer = ReadByte(m)&~128;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tv->thisplayer = MAX_CLIENTS-1;
|
||||||
|
/*tv->servertime =*/ ReadFloat(m);
|
||||||
|
}
|
||||||
ReadString(m, tv->mapname, sizeof(tv->mapname));
|
ReadString(m, tv->mapname, sizeof(tv->mapname));
|
||||||
|
|
||||||
Sys_Printf(tv->cluster, "Gamedir: %s\n", tv->gamedir);
|
Sys_Printf(tv->cluster, "Gamedir: %s\n", tv->gamedir);
|
||||||
|
@ -254,6 +260,13 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
||||||
memset(tv->staticsound, 0, sizeof(tv->staticsound));
|
memset(tv->staticsound, 0, sizeof(tv->staticsound));
|
||||||
|
|
||||||
memset(tv->players, 0, sizeof(tv->players));
|
memset(tv->players, 0, sizeof(tv->players));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
{
|
||||||
|
SendClientCommand(tv, "soundlist %i 0\n", tv->clservercount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseCDTrack(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
static void ParseCDTrack(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
|
@ -271,6 +284,7 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
qboolean fromproxy;
|
qboolean fromproxy;
|
||||||
|
|
||||||
ReadString(m, text, sizeof(text));
|
ReadString(m, text, sizeof(text));
|
||||||
|
Sys_Printf(tv->cluster, "stuffcmd: %s", text);
|
||||||
|
|
||||||
if (!strcmp(text, "skins\n"))
|
if (!strcmp(text, "skins\n"))
|
||||||
{
|
{
|
||||||
|
@ -285,6 +299,9 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
SendBufferToViewer(v, newcmd, sizeof(newcmd), true);
|
SendBufferToViewer(v, newcmd, sizeof(newcmd), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
SendClientCommand(tv, "begin %i\n", tv->clservercount);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!strncmp(text, "fullserverinfo ", 15))
|
else if (!strncmp(text, "fullserverinfo ", 15))
|
||||||
|
@ -325,7 +342,11 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!strncmp(text, "cmd ", 4))
|
else if (!strncmp(text, "cmd ", 4))
|
||||||
|
{
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
SendClientCommand(tv, "%s", text+4);
|
||||||
return; //commands the game server asked for are pointless.
|
return; //commands the game server asked for are pointless.
|
||||||
|
}
|
||||||
|
|
||||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||||
}
|
}
|
||||||
|
@ -500,8 +521,10 @@ void ParseSpawnStatic(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const usercmd_t nullcmd;
|
||||||
static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
||||||
{
|
{
|
||||||
|
usercmd_t nonnullcmd;
|
||||||
int flags;
|
int flags;
|
||||||
int num;
|
int num;
|
||||||
int i;
|
int i;
|
||||||
|
@ -515,50 +538,100 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
num = ReadByte(m);
|
num = ReadByte(m);
|
||||||
if (num >= MAX_CLIENTS)
|
if (num >= MAX_CLIENTS)
|
||||||
{
|
{
|
||||||
num = 0; // don't be fatal.
|
num = 0; // don't be fatal.
|
||||||
Sys_Printf(tv->cluster, "Too many svc_playerinfos, wrapping\n");
|
Sys_Printf(tv->cluster, "Too many svc_playerinfos, wrapping\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
tv->players[num].old = tv->players[num].current;
|
tv->players[num].old = tv->players[num].current;
|
||||||
|
|
||||||
flags = ReadShort(m);
|
if (tv->usequkeworldprotocols)
|
||||||
tv->players[num].gibbed = !!(flags & DF_GIB);
|
|
||||||
tv->players[num].dead = !!(flags & DF_DEAD);
|
|
||||||
tv->players[num].current.frame = ReadByte(m);
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
{
|
{
|
||||||
if (flags & (DF_ORIGIN << i))
|
tv->players[num].old = tv->players[num].current;
|
||||||
tv->players[num].current.origin[i] = ReadShort (m);
|
flags = (unsigned short)ReadShort (m);
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
tv->players[num].current.origin[0] = ReadShort (m);
|
||||||
{
|
tv->players[num].current.origin[1] = ReadShort (m);
|
||||||
if (flags & (DF_ANGLES << i))
|
tv->players[num].current.origin[2] = ReadShort (m);
|
||||||
|
|
||||||
|
tv->players[num].current.frame = ReadByte(m);
|
||||||
|
|
||||||
|
if (flags & PF_MSEC)
|
||||||
|
ReadByte (m);
|
||||||
|
|
||||||
|
if (flags & PF_COMMAND)
|
||||||
{
|
{
|
||||||
tv->players[num].current.angles[i] = ReadShort(m);
|
ReadDeltaUsercmd(m, &nullcmd, &nonnullcmd);
|
||||||
|
tv->players[num].current.angles[0] = nonnullcmd.angles[0];
|
||||||
|
tv->players[num].current.angles[1] = nonnullcmd.angles[1];
|
||||||
|
tv->players[num].current.angles[2] = nonnullcmd.angles[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0 ; i<3 ; i++)
|
||||||
|
{
|
||||||
|
if (flags & (PF_VELOCITY1<<i) )
|
||||||
|
ReadShort(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & PF_MODEL)
|
||||||
|
tv->players[num].current.modelindex = ReadByte (m);
|
||||||
|
else
|
||||||
|
tv->players[num].current.modelindex = tv->modelindex_player;
|
||||||
|
|
||||||
|
if (flags & PF_SKINNUM)
|
||||||
|
tv->players[num].current.skinnum = ReadByte (m);
|
||||||
|
else
|
||||||
|
tv->players[num].current.skinnum = 0;
|
||||||
|
|
||||||
|
if (flags & PF_EFFECTS)
|
||||||
|
tv->players[num].current.effects = ReadByte (m);
|
||||||
|
else
|
||||||
|
tv->players[num].current.effects = 0;
|
||||||
|
|
||||||
|
if (flags & PF_WEAPONFRAME)
|
||||||
|
tv->players[num].current.weaponframe = ReadByte (m);
|
||||||
|
else
|
||||||
|
tv->players[num].current.weaponframe = 0;
|
||||||
|
|
||||||
|
tv->players[num].active = (num != tv->thisplayer);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags = ReadShort(m);
|
||||||
|
tv->players[num].gibbed = !!(flags & DF_GIB);
|
||||||
|
tv->players[num].dead = !!(flags & DF_DEAD);
|
||||||
|
tv->players[num].current.frame = ReadByte(m);
|
||||||
|
|
||||||
if (flags & DF_MODEL)
|
for (i = 0; i < 3; i++)
|
||||||
tv->players[num].current.modelindex = ReadByte (m);
|
{
|
||||||
|
if (flags & (DF_ORIGIN << i))
|
||||||
|
tv->players[num].current.origin[i] = ReadShort (m);
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & DF_SKINNUM)
|
for (i = 0; i < 3; i++)
|
||||||
tv->players[num].current.skinnum = ReadByte (m);
|
{
|
||||||
|
if (flags & (DF_ANGLES << i))
|
||||||
|
{
|
||||||
|
tv->players[num].current.angles[i] = ReadShort(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & DF_EFFECTS)
|
if (flags & DF_MODEL)
|
||||||
tv->players[num].current.effects = ReadByte (m);
|
tv->players[num].current.modelindex = ReadByte (m);
|
||||||
|
|
||||||
if (flags & DF_WEAPONFRAME)
|
if (flags & DF_SKINNUM)
|
||||||
tv->players[num].current.weaponframe = ReadByte (m);
|
tv->players[num].current.skinnum = ReadByte (m);
|
||||||
|
|
||||||
tv->players[num].active = true;
|
if (flags & DF_EFFECTS)
|
||||||
|
tv->players[num].current.effects = ReadByte (m);
|
||||||
|
|
||||||
|
if (flags & DF_WEAPONFRAME)
|
||||||
|
tv->players[num].current.weaponframe = ReadByte (m);
|
||||||
|
|
||||||
|
tv->players[num].active = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
tv->players[num].leafcount = BSP_SphereLeafNums(tv->bsp, MAX_ENTITY_LEAFS, tv->players[num].leafs,
|
tv->players[num].leafcount = BSP_SphereLeafNums(tv->bsp, MAX_ENTITY_LEAFS, tv->players[num].leafs,
|
||||||
tv->players[num].current.origin[0]/8.0f,
|
tv->players[num].current.origin[0]/8.0f,
|
||||||
|
@ -671,8 +744,10 @@ static void ParseUpdatePing(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
|
|
||||||
static void ParseUpdateFrags(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
static void ParseUpdateFrags(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
{
|
{
|
||||||
|
int best;
|
||||||
int pnum;
|
int pnum;
|
||||||
int frags;
|
int frags;
|
||||||
|
char buffer[64];
|
||||||
pnum = ReadByte(m);
|
pnum = ReadByte(m);
|
||||||
frags = ReadShort(m);
|
frags = ReadShort(m);
|
||||||
|
|
||||||
|
@ -682,6 +757,26 @@ static void ParseUpdateFrags(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
Sys_Printf(tv->cluster, "svc_updatefrags: invalid player number\n");
|
Sys_Printf(tv->cluster, "svc_updatefrags: invalid player number\n");
|
||||||
|
|
||||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||||
|
|
||||||
|
if (!tv->usequkeworldprotocols)
|
||||||
|
return;
|
||||||
|
|
||||||
|
frags = -10000;
|
||||||
|
best = -1;
|
||||||
|
for (pnum = 0; pnum < MAX_CLIENTS; pnum++)
|
||||||
|
{
|
||||||
|
if (*tv->players[pnum].userinfo && !atoi(Info_ValueForKey(tv->players[pnum].userinfo, "*spectator", buffer, sizeof(buffer))))
|
||||||
|
if (frags < tv->players[pnum].frags)
|
||||||
|
{
|
||||||
|
best = pnum;
|
||||||
|
frags = tv->players[pnum].frags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best != tv->trackplayer)
|
||||||
|
{
|
||||||
|
SendClientCommand (tv, "ptrack %i\n", best);
|
||||||
|
tv->trackplayer = best;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseUpdateStat(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
static void ParseUpdateStat(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
|
@ -729,7 +824,7 @@ static void ParseUpdateStatLong(sv_t *tv, netmsg_t *m, int to, unsigned int mask
|
||||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParseUpdateUserinfo(sv_t *tv, netmsg_t *m)
|
static void ParseUpdateUserinfo(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
{
|
{
|
||||||
int pnum;
|
int pnum;
|
||||||
pnum = ReadByte(m);
|
pnum = ReadByte(m);
|
||||||
|
@ -743,6 +838,8 @@ static void ParseUpdateUserinfo(sv_t *tv, netmsg_t *m)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ParsePacketloss(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
static void ParsePacketloss(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||||
|
@ -957,6 +1054,7 @@ void ParseNails2(sv_t *tv, netmsg_t *m)
|
||||||
|
|
||||||
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
netmsg_t buf;
|
netmsg_t buf;
|
||||||
qboolean clearoldplayers = true;
|
qboolean clearoldplayers = true;
|
||||||
buf.cursize = length;
|
buf.cursize = length;
|
||||||
|
@ -1100,7 +1198,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case svc_updateuserinfo:
|
case svc_updateuserinfo:
|
||||||
ParseUpdateUserinfo(tv, &buf);
|
ParseUpdateUserinfo(tv, &buf, to, mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//#define svc_download 41 // [short] size [size bytes]
|
//#define svc_download 41 // [short] size [size bytes]
|
||||||
|
@ -1113,9 +1211,10 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
ReadByte(&buf);
|
ReadByte(&buf);
|
||||||
break;
|
break;
|
||||||
case svc_modellist:
|
case svc_modellist:
|
||||||
if (!ParseList(tv, &buf, tv->modellist, to, mask))
|
i = ParseList(tv, &buf, tv->modellist, to, mask);
|
||||||
|
if (!i)
|
||||||
{
|
{
|
||||||
int i;
|
int j;
|
||||||
if (tv->bsp)
|
if (tv->bsp)
|
||||||
BSP_Free(tv->bsp);
|
BSP_Free(tv->bsp);
|
||||||
|
|
||||||
|
@ -1125,16 +1224,30 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
tv->bsp = BSP_LoadModel(tv->cluster, tv->gamedir, tv->modellist[1].name);
|
tv->bsp = BSP_LoadModel(tv->cluster, tv->gamedir, tv->modellist[1].name);
|
||||||
|
|
||||||
tv->numinlines = 0;
|
tv->numinlines = 0;
|
||||||
for (i = 2; i < 256; i++)
|
for (j = 2; j < 256; j++)
|
||||||
{
|
{
|
||||||
if (*tv->modellist[i].name != '*')
|
if (*tv->modellist[j].name != '*')
|
||||||
break;
|
break;
|
||||||
tv->numinlines = i;
|
tv->numinlines = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
SendClientCommand(tv, "modellist %i %i\n", tv->clservercount, i);
|
||||||
|
else
|
||||||
|
SendClientCommand(tv, "prespawn %i 0 %i\n", tv->clservercount, BSP_Checksum(tv->bsp));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case svc_soundlist:
|
case svc_soundlist:
|
||||||
ParseList(tv, &buf, tv->soundlist, to, mask);
|
i = ParseList(tv, &buf, tv->soundlist, to, mask);
|
||||||
|
if (tv->usequkeworldprotocols)
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
SendClientCommand(tv, "soundlist %i %i\n", tv->clservercount, i);
|
||||||
|
else
|
||||||
|
SendClientCommand(tv, "modellist %i 0\n", tv->clservercount);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case svc_packetentities:
|
case svc_packetentities:
|
||||||
FlushPacketEntities(tv);
|
FlushPacketEntities(tv);
|
||||||
|
@ -1145,7 +1258,9 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||||
ParsePacketEntities(tv, &buf);
|
ParsePacketEntities(tv, &buf);
|
||||||
break;
|
break;
|
||||||
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||||
//#define svc_entgravity 50 // gravity change, for prediction
|
case svc_entgravity: // gravity change, for prediction
|
||||||
|
ReadFloat(&buf);
|
||||||
|
break;
|
||||||
case svc_setinfo:
|
case svc_setinfo:
|
||||||
ParseSetInfo(tv, &buf);
|
ParseSetInfo(tv, &buf);
|
||||||
break;
|
break;
|
||||||
|
|
36
fteqtv/qtv.h
36
fteqtv/qtv.h
|
@ -164,6 +164,7 @@ typedef struct {
|
||||||
|
|
||||||
int reliable_length;
|
int reliable_length;
|
||||||
qboolean drop;
|
qboolean drop;
|
||||||
|
qboolean isclient;
|
||||||
|
|
||||||
netmsg_t message;
|
netmsg_t message;
|
||||||
char message_buf[MAX_MSGLEN]; //reliable message being built
|
char message_buf[MAX_MSGLEN]; //reliable message being built
|
||||||
|
@ -301,8 +302,17 @@ typedef struct {
|
||||||
unsigned short leafs[MAX_ENTITY_LEAFS];
|
unsigned short leafs[MAX_ENTITY_LEAFS];
|
||||||
} entity_t;
|
} entity_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char msec;
|
||||||
|
unsigned short angles[3];
|
||||||
|
short forwardmove, sidemove, upmove;
|
||||||
|
unsigned char buttons;
|
||||||
|
unsigned char impulse;
|
||||||
|
} usercmd_t;
|
||||||
|
|
||||||
struct sv_s {
|
struct sv_s {
|
||||||
netadr_t serveraddress;
|
netadr_t serveraddress;
|
||||||
|
netchan_t netchan;
|
||||||
|
|
||||||
unsigned char buffer[MAX_PROXY_BUFFER]; //this doesn't cycle.
|
unsigned char buffer[MAX_PROXY_BUFFER]; //this doesn't cycle.
|
||||||
int buffersize; //it memmoves down
|
int buffersize; //it memmoves down
|
||||||
|
@ -339,12 +349,24 @@ struct sv_s {
|
||||||
filename_t modellist[MAX_MODELS];
|
filename_t modellist[MAX_MODELS];
|
||||||
filename_t soundlist[MAX_SOUNDS];
|
filename_t soundlist[MAX_SOUNDS];
|
||||||
int modelindex_spike; // qw is wierd.
|
int modelindex_spike; // qw is wierd.
|
||||||
|
int modelindex_player; // qw is wierd.
|
||||||
|
|
||||||
|
qboolean usequkeworldprotocols;
|
||||||
|
int challenge;
|
||||||
|
unsigned short qport;
|
||||||
|
int isconnected;
|
||||||
|
int clservercount;
|
||||||
|
unsigned int nextsendpings;
|
||||||
|
unsigned int trackplayer;
|
||||||
|
int thisplayer;
|
||||||
|
unsigned timeout;
|
||||||
|
|
||||||
FILE *file;
|
FILE *file;
|
||||||
unsigned int filelength;
|
unsigned int filelength;
|
||||||
SOCKET sourcesock;
|
SOCKET sourcesock;
|
||||||
|
|
||||||
SOCKET listenmvd; //tcp + mvd protocol
|
SOCKET listenmvd; //tcp + mvd protocol
|
||||||
|
int tcplistenportnum;
|
||||||
|
|
||||||
oproxy_t *proxies;
|
oproxy_t *proxies;
|
||||||
int numproxies;
|
int numproxies;
|
||||||
|
@ -355,9 +377,13 @@ struct sv_s {
|
||||||
unsigned int curtime;
|
unsigned int curtime;
|
||||||
unsigned int oldpackettime;
|
unsigned int oldpackettime;
|
||||||
unsigned int nextpackettime;
|
unsigned int nextpackettime;
|
||||||
unsigned int nextconnectattemp;
|
unsigned int nextconnectattempt;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
qboolean disconnectwhennooneiswatching;
|
||||||
|
unsigned int numviewers;
|
||||||
|
|
||||||
int tcplistenportnum;
|
|
||||||
|
|
||||||
|
|
||||||
cluster_t *cluster;
|
cluster_t *cluster;
|
||||||
|
@ -499,7 +525,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen);
|
||||||
#define svc_packetentities 47 // [...]
|
#define svc_packetentities 47 // [...]
|
||||||
#define svc_deltapacketentities 48 // [...]
|
#define svc_deltapacketentities 48 // [...]
|
||||||
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||||
//#define svc_entgravity 50 // gravity change, for prediction
|
#define svc_entgravity 50 // gravity change, for prediction
|
||||||
#define svc_setinfo 51 // setinfo on a client
|
#define svc_setinfo 51 // setinfo on a client
|
||||||
#define svc_serverinfo 52 // serverinfo
|
#define svc_serverinfo 52 // serverinfo
|
||||||
#define svc_updatepl 53 // [qbyte] [qbyte]
|
#define svc_updatepl 53 // [qbyte] [qbyte]
|
||||||
|
@ -596,7 +622,7 @@ void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean re
|
||||||
void QW_PrintfToViewer(viewer_t *v, char *format, ...);
|
void QW_PrintfToViewer(viewer_t *v, char *format, ...);
|
||||||
void QW_StuffcmdToViewer(viewer_t *v, char *format, ...);
|
void QW_StuffcmdToViewer(viewer_t *v, char *format, ...);
|
||||||
|
|
||||||
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport);
|
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, ...);
|
void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...);
|
||||||
int Netchan_IsLocal (netadr_t adr);
|
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, char *data, netadr_t adr);
|
||||||
|
@ -621,6 +647,6 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m
|
||||||
void Sys_Printf(cluster_t *cluster, char *fmt, ...);
|
void Sys_Printf(cluster_t *cluster, char *fmt, ...);
|
||||||
|
|
||||||
qboolean Net_FileProxy(sv_t *qtv, char *filename);
|
qboolean Net_FileProxy(sv_t *qtv, char *filename);
|
||||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force);
|
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose);
|
||||||
SOCKET Net_MVDListen(int port);
|
SOCKET Net_MVDListen(int port);
|
||||||
qboolean Net_StopFileProxy(sv_t *qtv);
|
qboolean Net_StopFileProxy(sv_t *qtv);
|
||||||
|
|
208
fteqtv/qw.c
208
fteqtv/qw.c
|
@ -20,14 +20,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "qtv.h"
|
#include "qtv.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int snprintf(char *buffer, int buffersize, char *format, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
int ret;
|
||||||
|
va_start (argptr, format);
|
||||||
|
ret = _vsnprintf (buf, buffersize, format, argptr);
|
||||||
|
buf[buffersize - 1] = '\0';
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char msec;
|
|
||||||
unsigned short angles[3];
|
|
||||||
short forwardmove, sidemove, upmove;
|
|
||||||
unsigned char buttons;
|
|
||||||
unsigned char impulse;
|
|
||||||
} usercmd_t;
|
|
||||||
const usercmd_t nullcmd;
|
const usercmd_t nullcmd;
|
||||||
|
|
||||||
#define CM_ANGLE1 (1<<0)
|
#define CM_ANGLE1 (1<<0)
|
||||||
|
@ -417,6 +423,20 @@ int SendList(sv_t *qtv, int first, const filename_t *list, int svc, netmsg_t *ms
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QW_SetViewersServer(viewer_t *viewer, sv_t *sv)
|
||||||
|
{
|
||||||
|
if (viewer->server)
|
||||||
|
viewer->server->numviewers--;
|
||||||
|
viewer->server = sv;
|
||||||
|
if (viewer->server)
|
||||||
|
viewer->server->numviewers++;
|
||||||
|
QW_StuffcmdToViewer(viewer, "cmd new\n");
|
||||||
|
viewer->servercount++;
|
||||||
|
viewer->origin[0] = 0;
|
||||||
|
viewer->origin[1] = 0;
|
||||||
|
viewer->origin[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//fixme: will these want to have state?..
|
//fixme: will these want to have state?..
|
||||||
int NewChallenge(netadr_t *addr)
|
int NewChallenge(netadr_t *addr)
|
||||||
{
|
{
|
||||||
|
@ -431,6 +451,7 @@ qboolean ChallengePasses(netadr_t *addr, int challenge)
|
||||||
|
|
||||||
void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
||||||
{
|
{
|
||||||
|
sv_t *initialserver;
|
||||||
viewer_t *viewer;
|
viewer_t *viewer;
|
||||||
|
|
||||||
char qport[32];
|
char qport[32];
|
||||||
|
@ -451,23 +472,33 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
||||||
|
|
||||||
|
|
||||||
viewer = malloc(sizeof(viewer_t));
|
viewer = malloc(sizeof(viewer_t));
|
||||||
|
if (!viewer)
|
||||||
|
{
|
||||||
|
Netchan_OutOfBandPrint(cluster, cluster->qwdsocket, *addr, "n" "Out of memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
memset(viewer, 0, sizeof(viewer_t));
|
memset(viewer, 0, sizeof(viewer_t));
|
||||||
|
|
||||||
viewer->trackplayer = -1;
|
viewer->trackplayer = -1;
|
||||||
Netchan_Setup (cluster->qwdsocket, &viewer->netchan, *addr, atoi(qport));
|
Netchan_Setup (cluster->qwdsocket, &viewer->netchan, *addr, atoi(qport), false);
|
||||||
|
|
||||||
viewer->next = cluster->viewers;
|
viewer->next = cluster->viewers;
|
||||||
cluster->viewers = viewer;
|
cluster->viewers = viewer;
|
||||||
viewer->delta_frame = -1;
|
viewer->delta_frame = -1;
|
||||||
|
|
||||||
|
initialserver = NULL;
|
||||||
if (cluster->numservers == 1)
|
if (cluster->numservers == 1)
|
||||||
{
|
{
|
||||||
viewer->server = cluster->servers;
|
initialserver = cluster->servers;
|
||||||
if (!viewer->server->modellist[1].name[0])
|
if (!initialserver->modellist[1].name[0])
|
||||||
viewer->server = NULL; //damn, that server isn't ready
|
initialserver = NULL; //damn, that server isn't ready
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!viewer->server)
|
viewer->server = initialserver;
|
||||||
|
if (viewer->server)
|
||||||
|
viewer->server->numviewers++;
|
||||||
|
|
||||||
|
if (!initialserver)
|
||||||
viewer->menunum = 1;
|
viewer->menunum = 1;
|
||||||
|
|
||||||
cluster->numviewers++;
|
cluster->numviewers++;
|
||||||
|
@ -1078,17 +1109,11 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
||||||
}
|
}
|
||||||
else if (!strcmp(v->expectcommand, "addserver"))
|
else if (!strcmp(v->expectcommand, "addserver"))
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
_snprintf(buf, sizeof(buf), "tcp:%s", message);
|
|
||||||
buf[suzeof(buf)-1] = '\0';
|
|
||||||
#else
|
|
||||||
snprintf(buf, sizeof(buf), "tcp:%s", message);
|
snprintf(buf, sizeof(buf), "tcp:%s", message);
|
||||||
#endif
|
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||||
qtv = QTV_NewServerConnection(cluster, buf, false);
|
|
||||||
if (qtv)
|
if (qtv)
|
||||||
{
|
{
|
||||||
v->server = qtv;
|
QW_SetViewersServer(v, qtv);
|
||||||
QW_StuffcmdToViewer(v, "cmd new\n");
|
|
||||||
QW_PrintfToViewer(v, "Connected\n", message);
|
QW_PrintfToViewer(v, "Connected\n", message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1110,22 +1135,46 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
||||||
}
|
}
|
||||||
else if (!strcmp(v->expectcommand, "adddemo"))
|
else if (!strcmp(v->expectcommand, "adddemo"))
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
_snprintf(buf, sizeof(buf), "file:%s", message);
|
|
||||||
buf[sizeof(buf)-1] = '\0';
|
|
||||||
#else
|
|
||||||
snprintf(buf, sizeof(buf), "file:%s", message);
|
snprintf(buf, sizeof(buf), "file:%s", message);
|
||||||
#endif
|
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||||
qtv = QTV_NewServerConnection(cluster, buf, false);
|
|
||||||
if (!qtv)
|
if (!qtv)
|
||||||
QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message);
|
QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v->server = qtv;
|
QW_SetViewersServer(v, qtv);
|
||||||
QW_StuffcmdToViewer(v, "cmd new\n");
|
|
||||||
QW_PrintfToViewer(v, "Opened demo file.\n", message);
|
QW_PrintfToViewer(v, "Opened demo file.\n", message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(v->expectcommand, "setmvdport"))
|
||||||
|
{
|
||||||
|
int newp;
|
||||||
|
int news;
|
||||||
|
if (qtv)
|
||||||
|
{
|
||||||
|
newp = atoi(message);
|
||||||
|
|
||||||
|
if (newp)
|
||||||
|
{
|
||||||
|
news = Net_MVDListen(newp);
|
||||||
|
|
||||||
|
if (news != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
if (qtv->listenmvd != INVALID_SOCKET)
|
||||||
|
closesocket(qtv->listenmvd);
|
||||||
|
qtv->listenmvd = news;
|
||||||
|
qtv->tcplistenportnum = newp;
|
||||||
|
qtv->disconnectwhennooneiswatching = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (qtv->listenmvd != INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
closesocket(qtv->listenmvd);
|
||||||
|
qtv->listenmvd = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QW_PrintfToViewer(v, "You were disconnected from that stream\n");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QW_PrintfToViewer(v, "Command %s was not recognised\n", v->expectcommand);
|
QW_PrintfToViewer(v, "Command %s was not recognised\n", v->expectcommand);
|
||||||
|
@ -1134,18 +1183,68 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
||||||
*v->expectcommand = '\0';
|
*v->expectcommand = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*v->expectcommand = '\0';
|
if (!strncmp(message, ".qw ", 4))
|
||||||
|
{
|
||||||
|
message += 4;
|
||||||
|
snprintf(buf, sizeof(buf), "udp:%s", message);
|
||||||
|
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||||
|
if (qtv)
|
||||||
|
{
|
||||||
|
// QW_SetViewersServer(v, qtv);
|
||||||
|
QW_PrintfToViewer(v, "Connected\n", message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", message);
|
||||||
|
}
|
||||||
|
else if (!strncmp(message, ".connect ", 9))
|
||||||
|
{
|
||||||
|
message += 9;
|
||||||
|
snprintf(buf, sizeof(buf), "tcp:%s", message);
|
||||||
|
qtv = QTV_NewServerConnection(cluster, buf, false, true);
|
||||||
|
if (qtv)
|
||||||
|
{
|
||||||
|
QW_SetViewersServer(v, qtv);
|
||||||
|
QW_PrintfToViewer(v, "Connected\n", message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", message);
|
||||||
|
}
|
||||||
|
else if (!strncmp(message, ".demo ", 6))
|
||||||
|
{
|
||||||
|
message += 6;
|
||||||
|
snprintf(buf, sizeof(buf), "file:%s", message);
|
||||||
|
qtv = QTV_NewServerConnection(cluster, buf, false, true);
|
||||||
|
if (qtv)
|
||||||
|
{
|
||||||
|
QW_SetViewersServer(v, qtv);
|
||||||
|
QW_PrintfToViewer(v, "Connected\n", message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", message);
|
||||||
|
}
|
||||||
|
else if (!strncmp(message, ".disconnect", 11))
|
||||||
|
{
|
||||||
|
QW_SetViewersServer(v, NULL);
|
||||||
|
QW_PrintfToViewer(v, "Connected\n", message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cluster->notalking)
|
||||||
|
return;
|
||||||
|
|
||||||
InitNetMsg(&msg, buf, sizeof(buf));
|
*v->expectcommand = '\0';
|
||||||
|
|
||||||
WriteByte(&msg, svc_print);
|
InitNetMsg(&msg, buf, sizeof(buf));
|
||||||
WriteByte(&msg, 3); //PRINT_CHAT
|
|
||||||
WriteString2(&msg, v->name);
|
|
||||||
WriteString2(&msg, "\x8d ");
|
|
||||||
WriteString2(&msg, message);
|
|
||||||
WriteString(&msg, "\n");
|
|
||||||
|
|
||||||
Broadcast(cluster, msg.data, msg.cursize);
|
WriteByte(&msg, svc_print);
|
||||||
|
WriteByte(&msg, 3); //PRINT_CHAT
|
||||||
|
WriteString2(&msg, v->name);
|
||||||
|
WriteString2(&msg, "\x8d ");
|
||||||
|
WriteString2(&msg, message);
|
||||||
|
WriteString(&msg, "\n");
|
||||||
|
|
||||||
|
Broadcast(cluster, msg.data, msg.cursize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewer_t *QW_IsOn(cluster_t *cluster, char *name)
|
viewer_t *QW_IsOn(cluster_t *cluster, char *name)
|
||||||
|
@ -1230,7 +1329,12 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
||||||
// printf("stringcmd: %s\n", buf);
|
// printf("stringcmd: %s\n", buf);
|
||||||
|
|
||||||
if (!strcmp(buf, "new"))
|
if (!strcmp(buf, "new"))
|
||||||
SendServerData(qtv, v);
|
{
|
||||||
|
if (qtv->parsingconnectiondata)
|
||||||
|
QW_StuffcmdToViewer(v, "cmd new\n");
|
||||||
|
else
|
||||||
|
SendServerData(qtv, v);
|
||||||
|
}
|
||||||
else if (!strncmp(buf, "modellist ", 10))
|
else if (!strncmp(buf, "modellist ", 10))
|
||||||
{
|
{
|
||||||
char *cmd = buf+10;
|
char *cmd = buf+10;
|
||||||
|
@ -1357,9 +1461,9 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
||||||
else if (!strncmp(buf, "pings", 5))
|
else if (!strncmp(buf, "pings", 5))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (!strncmp(buf, "say \"", 5) && !cluster->notalking)
|
else if (!strncmp(buf, "say \"", 5))
|
||||||
QTV_Say(cluster, qtv, v, buf+5);
|
QTV_Say(cluster, qtv, v, buf+5);
|
||||||
else if (!strncmp(buf, "say ", 4) && !cluster->notalking)
|
else if (!strncmp(buf, "say ", 4))
|
||||||
QTV_Say(cluster, qtv, v, buf+4);
|
QTV_Say(cluster, qtv, v, buf+4);
|
||||||
|
|
||||||
else if (!strncmp(buf, "servers", 7))
|
else if (!strncmp(buf, "servers", 7))
|
||||||
|
@ -1368,8 +1472,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
||||||
}
|
}
|
||||||
else if (!strncmp(buf, "reset", 5))
|
else if (!strncmp(buf, "reset", 5))
|
||||||
{
|
{
|
||||||
QW_StuffcmdToViewer(v, "cmd new\n");
|
QW_SetViewersServer(v, NULL);
|
||||||
v->server = NULL;
|
|
||||||
v->menunum = 1;
|
v->menunum = 1;
|
||||||
}
|
}
|
||||||
else if (!strncmp(buf, "admin", 5))
|
else if (!strncmp(buf, "admin", 5))
|
||||||
|
@ -1514,10 +1617,12 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
||||||
if (viewer->server)
|
if (viewer->server)
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
|
sv = viewer->server;
|
||||||
if (i++ == viewer->menuop)
|
if (i++ == viewer->menuop)
|
||||||
{ //mvd port
|
{ //mvd port
|
||||||
QW_StuffcmdToViewer(viewer, "echo You will need to reconnect\n");
|
WriteString(&m, "echo Please enter a new tcp port number\nmessagemode\n");
|
||||||
cluster->qwlistenportnum += buttonnum?-1:1;
|
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||||
|
strcpy(viewer->expectcommand, "setmvdport");
|
||||||
}
|
}
|
||||||
if (i++ == viewer->menuop)
|
if (i++ == viewer->menuop)
|
||||||
{ //disconnect
|
{ //disconnect
|
||||||
|
@ -1534,8 +1639,9 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
||||||
case 1:
|
case 1:
|
||||||
if (!cluster->servers)
|
if (!cluster->servers)
|
||||||
{
|
{
|
||||||
WriteString(&m, "messagemode\n");
|
WriteString(&m, "echo Please enter a server ip\nmessagemode\n");
|
||||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||||
|
strcpy(viewer->expectcommand, "insecadddemo");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1560,9 +1666,7 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteString(&m, "cmd new\n");
|
QW_SetViewersServer(viewer, sv);
|
||||||
viewer->servercount++;
|
|
||||||
viewer->server = sv;
|
|
||||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||||
viewer->menunum = 0;
|
viewer->menunum = 0;
|
||||||
viewer->thinksitsconnected = false;
|
viewer->thinksitsconnected = false;
|
||||||
|
@ -1675,7 +1779,10 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer)
|
||||||
i = 0;
|
i = 0;
|
||||||
WriteString2(&m, " port");
|
WriteString2(&m, " port");
|
||||||
WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
|
WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : ");
|
||||||
sprintf(str, "%-20i", sv->tcplistenportnum);
|
if (sv->listenmvd == INVALID_SOCKET)
|
||||||
|
sprintf(str, "!%-19i", sv->tcplistenportnum);
|
||||||
|
else
|
||||||
|
sprintf(str, "%-20i", sv->tcplistenportnum);
|
||||||
WriteString2(&m, str);
|
WriteString2(&m, str);
|
||||||
WriteString2(&m, "\n");
|
WriteString2(&m, "\n");
|
||||||
|
|
||||||
|
@ -1845,6 +1952,9 @@ void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
|
||||||
free(viewer->backbuf[i].data);
|
free(viewer->backbuf[i].data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewer->server)
|
||||||
|
viewer->server->numviewers--;
|
||||||
|
|
||||||
free(viewer);
|
free(viewer);
|
||||||
|
|
||||||
cluster->numviewers--;
|
cluster->numviewers--;
|
||||||
|
|
|
@ -347,7 +347,19 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
||||||
memmove(arg[1]+4, arg[1], ARG_LEN-5);
|
memmove(arg[1]+4, arg[1], ARG_LEN-5);
|
||||||
strncpy(arg[1], "tcp:", 4);
|
strncpy(arg[1], "tcp:", 4);
|
||||||
|
|
||||||
if (!QTV_NewServerConnection(cluster, arg[1], false))
|
if (!QTV_NewServerConnection(cluster, arg[1], false, !strcmp(arg[0], "connect")))
|
||||||
|
return "Failed to connect to server, connection aborted\n";
|
||||||
|
return "Connection registered\n";
|
||||||
|
}
|
||||||
|
else if (!strcmp(arg[0], "qw"))
|
||||||
|
{
|
||||||
|
if (!*arg[1])
|
||||||
|
return "connect requires an ip:port parameter\n";
|
||||||
|
|
||||||
|
memmove(arg[1]+4, arg[1], ARG_LEN-5);
|
||||||
|
strncpy(arg[1], "udp:", 4);
|
||||||
|
|
||||||
|
if (!QTV_NewServerConnection(cluster, arg[1], false, false))
|
||||||
return "Failed to connect to server, connection aborted\n";
|
return "Failed to connect to server, connection aborted\n";
|
||||||
return "Connection registered\n";
|
return "Connection registered\n";
|
||||||
}
|
}
|
||||||
|
@ -363,7 +375,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
||||||
memmove(arg[1]+5, arg[1], ARG_LEN-6);
|
memmove(arg[1]+5, arg[1], ARG_LEN-6);
|
||||||
strncpy(arg[1], "file:", 5);
|
strncpy(arg[1], "file:", 5);
|
||||||
|
|
||||||
if (!QTV_NewServerConnection(cluster, arg[1], false))
|
if (!QTV_NewServerConnection(cluster, arg[1], false, false))
|
||||||
return "Failed to connect to server, connection aborted\n";
|
return "Failed to connect to server, connection aborted\n";
|
||||||
return "Connection registered\n";
|
return "Connection registered\n";
|
||||||
}
|
}
|
||||||
|
@ -558,7 +570,7 @@ char *Server_Rcon_Dispatch(sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int siz
|
||||||
else if (!strcmp(arg[0], "disconnect"))
|
else if (!strcmp(arg[0], "disconnect"))
|
||||||
{
|
{
|
||||||
QTV_Shutdown(qtv);
|
QTV_Shutdown(qtv);
|
||||||
return NULL;
|
return "Disconnected\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!strcmp(arg[0], "file") || !strcmp(arg[0], "play") || !strcmp(arg[0], "playdemo"))
|
else if (!strcmp(arg[0], "file") || !strcmp(arg[0], "play") || !strcmp(arg[0], "playdemo"))
|
||||||
|
@ -630,8 +642,10 @@ char *Server_Rcon_Dispatch(sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int siz
|
||||||
|
|
||||||
if (news != INVALID_SOCKET)
|
if (news != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
closesocket(qtv->listenmvd);
|
if (qtv->listenmvd != INVALID_SOCKET)
|
||||||
|
closesocket(qtv->listenmvd);
|
||||||
qtv->listenmvd = news;
|
qtv->listenmvd = news;
|
||||||
|
qtv->disconnectwhennooneiswatching = false;
|
||||||
qtv->tcplistenportnum = newp;
|
qtv->tcplistenportnum = newp;
|
||||||
return "Opened tcp port\n";
|
return "Opened tcp port\n";
|
||||||
}
|
}
|
||||||
|
|
267
fteqtv/source.c
267
fteqtv/source.c
|
@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "qtv.h"
|
#include "qtv.h"
|
||||||
|
|
||||||
#define RECONNECT_TIME (1000*30)
|
#define RECONNECT_TIME (1000*30)
|
||||||
|
#define UDPRECONNECT_TIME (1000)
|
||||||
|
#define PINGSINTERVAL_TIME (1000*5)
|
||||||
|
#define UDPTIMEOUT_LENGTH (1000*20)
|
||||||
|
|
||||||
|
|
||||||
qboolean NET_StringToAddr (char *s, netadr_t *sadr)
|
qboolean NET_StringToAddr (char *s, netadr_t *sadr)
|
||||||
|
@ -202,34 +205,11 @@ SOCKET Net_MVDListen(int port)
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean Net_ConnectToServer(sv_t *qtv, char *ip)
|
qboolean Net_ConnectToTCPServer(sv_t *qtv, char *ip)
|
||||||
{
|
{
|
||||||
netadr_t from;
|
netadr_t from;
|
||||||
unsigned long nonblocking = true;
|
unsigned long nonblocking = true;
|
||||||
|
|
||||||
if (!strncmp(ip, "file:", 5))
|
|
||||||
{
|
|
||||||
qtv->sourcesock = INVALID_SOCKET;
|
|
||||||
qtv->file = fopen(ip+5, "rb");
|
|
||||||
if (qtv->file)
|
|
||||||
{
|
|
||||||
fseek(qtv->file, 0, SEEK_END);
|
|
||||||
qtv->filelength = ftell(qtv->file);
|
|
||||||
fseek(qtv->file, 0, SEEK_SET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Sys_Printf(qtv->cluster, "Unable to open file %s\n", ip+5);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qtv->nextconnectattemp = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
|
|
||||||
|
|
||||||
if (strncmp(ip, "tcp:", 4))
|
|
||||||
{
|
|
||||||
Sys_Printf(qtv->cluster, "Unknown source type %s\n", ip);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NET_StringToAddr(ip+4, &qtv->serveraddress))
|
if (!NET_StringToAddr(ip+4, &qtv->serveraddress))
|
||||||
{
|
{
|
||||||
Sys_Printf(qtv->cluster, "Unable to resolve %s\n", ip);
|
Sys_Printf(qtv->cluster, "Unable to resolve %s\n", ip);
|
||||||
|
@ -264,10 +244,78 @@ qboolean Net_ConnectToServer(sv_t *qtv, char *ip)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
qboolean Net_ConnectToUDPServer(sv_t *qtv, char *ip)
|
||||||
|
{
|
||||||
|
netadr_t from;
|
||||||
|
unsigned long nonblocking = true;
|
||||||
|
|
||||||
|
if (!NET_StringToAddr(ip+4, &qtv->serveraddress))
|
||||||
|
{
|
||||||
|
Sys_Printf(qtv->cluster, "Unable to resolve %s\n", ip);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
qtv->sourcesock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (qtv->sourcesock == INVALID_SOCKET)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(&from, 0, sizeof(from));
|
||||||
|
((struct sockaddr*)&from)->sa_family = ((struct sockaddr*)&qtv->serveraddress)->sa_family;
|
||||||
|
if (bind(qtv->sourcesock, (struct sockaddr *)&from, sizeof(from)) == -1)
|
||||||
|
{
|
||||||
|
closesocket(qtv->sourcesock);
|
||||||
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctlsocket (qtv->sourcesock, FIONBIO, &nonblocking) == -1)
|
||||||
|
{
|
||||||
|
closesocket(qtv->sourcesock);
|
||||||
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qtv->qport = Sys_Milliseconds()*1000+Sys_Milliseconds();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qboolean Net_ConnectToServer(sv_t *qtv, char *ip)
|
||||||
|
{
|
||||||
|
qtv->usequkeworldprotocols = false;
|
||||||
|
|
||||||
|
if (!strncmp(ip, "file:", 5))
|
||||||
|
{
|
||||||
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
qtv->file = fopen(ip+5, "rb");
|
||||||
|
if (qtv->file)
|
||||||
|
{
|
||||||
|
fseek(qtv->file, 0, SEEK_END);
|
||||||
|
qtv->filelength = ftell(qtv->file);
|
||||||
|
fseek(qtv->file, 0, SEEK_SET);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Sys_Printf(qtv->cluster, "Unable to open file %s\n", ip+5);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qtv->nextconnectattempt = qtv->curtime + RECONNECT_TIME; //wait half a minuite before trying to reconnect
|
||||||
|
|
||||||
|
if (!strncmp(ip, "udp:", 4))
|
||||||
|
{
|
||||||
|
qtv->usequkeworldprotocols = true;
|
||||||
|
return Net_ConnectToUDPServer(qtv, ip);
|
||||||
|
}
|
||||||
|
else if (!strncmp(ip, "tcp:", 4))
|
||||||
|
return Net_ConnectToTCPServer(qtv, ip);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Sys_Printf(qtv->cluster, "Unknown source type %s\n", ip);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Net_FindProxies(sv_t *qtv)
|
void Net_FindProxies(sv_t *qtv)
|
||||||
{
|
{
|
||||||
oproxy_t *prox;
|
oproxy_t *prox;
|
||||||
|
@ -286,6 +334,11 @@ void Net_FindProxies(sv_t *qtv)
|
||||||
}
|
}
|
||||||
|
|
||||||
prox = malloc(sizeof(*prox));
|
prox = malloc(sizeof(*prox));
|
||||||
|
if (!prox)
|
||||||
|
{//out of mem?
|
||||||
|
closesocket(sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
memset(prox, 0, sizeof(*prox));
|
memset(prox, 0, sizeof(*prox));
|
||||||
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
||||||
prox->sock = sock;
|
prox->sock = sock;
|
||||||
|
@ -309,6 +362,8 @@ qboolean Net_FileProxy(sv_t *qtv, char *filename)
|
||||||
//no full proxy check, this is going to be used by proxy admins, who won't want to have to raise the limit to start recording.
|
//no full proxy check, this is going to be used by proxy admins, who won't want to have to raise the limit to start recording.
|
||||||
|
|
||||||
prox = malloc(sizeof(*prox));
|
prox = malloc(sizeof(*prox));
|
||||||
|
if (!prox)
|
||||||
|
return false;
|
||||||
memset(prox, 0, sizeof(*prox));
|
memset(prox, 0, sizeof(*prox));
|
||||||
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
||||||
prox->sock = INVALID_SOCKET;
|
prox->sock = INVALID_SOCKET;
|
||||||
|
@ -865,8 +920,8 @@ qboolean QTV_Connect(sv_t *qtv, char *serverurl)
|
||||||
|
|
||||||
void QTV_Shutdown(sv_t *qtv)
|
void QTV_Shutdown(sv_t *qtv)
|
||||||
{
|
{
|
||||||
return;
|
oproxy_t *prox;
|
||||||
/*
|
oproxy_t *old;
|
||||||
viewer_t *v;
|
viewer_t *v;
|
||||||
sv_t *peer;
|
sv_t *peer;
|
||||||
cluster_t *cluster;
|
cluster_t *cluster;
|
||||||
|
@ -888,6 +943,8 @@ void QTV_Shutdown(sv_t *qtv)
|
||||||
fclose(qtv->file);
|
fclose(qtv->file);
|
||||||
qtv->file = NULL;
|
qtv->file = NULL;
|
||||||
}
|
}
|
||||||
|
if (qtv->listenmvd != INVALID_SOCKET)
|
||||||
|
closesocket(qtv->listenmvd);
|
||||||
BSP_Free(qtv->bsp);
|
BSP_Free(qtv->bsp);
|
||||||
qtv->bsp = NULL;
|
qtv->bsp = NULL;
|
||||||
|
|
||||||
|
@ -910,13 +967,25 @@ void QTV_Shutdown(sv_t *qtv)
|
||||||
{
|
{
|
||||||
if (v->server == qtv)
|
if (v->server == qtv)
|
||||||
{
|
{
|
||||||
v->server = NULL;
|
QW_SetViewersServer(v, NULL);
|
||||||
v->menunum = 1;
|
v->menunum = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (prox = qtv->proxies; prox; )
|
||||||
|
{
|
||||||
|
if (prox->file)
|
||||||
|
fclose(prox->file);
|
||||||
|
if (prox->sock != INVALID_SOCKET)
|
||||||
|
closesocket(prox->sock);
|
||||||
|
old = prox;
|
||||||
|
prox = prox->next;
|
||||||
|
free(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
free(qtv);
|
free(qtv);
|
||||||
*/
|
cluster->numservers--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1199,9 +1268,81 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SendClientCommand(sv_t *qtv, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
va_start (argptr, fmt);
|
||||||
|
#ifdef _WIN32
|
||||||
|
_vsnprintf (buf, sizeof(buf) - 1, fmt, argptr);
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
#else
|
||||||
|
vsnprintf (buf, sizeof(buf), fmt, argptr);
|
||||||
|
#endif // _WIN32
|
||||||
|
va_end (argptr);
|
||||||
|
|
||||||
|
WriteByte(&qtv->netchan.message, clc_stringcmd);
|
||||||
|
WriteString(&qtv->netchan.message, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTV_ParseQWStream(sv_t *qtv)
|
||||||
|
{
|
||||||
|
char buffer[1500];
|
||||||
|
netadr_t from;
|
||||||
|
int fromlen;
|
||||||
|
int readlen;
|
||||||
|
netmsg_t msg;
|
||||||
|
fromlen = sizeof(from); //bug: this won't work on (free)bsd
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
readlen = recvfrom(qtv->sourcesock, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&from, &fromlen);
|
||||||
|
if (readlen < 0)
|
||||||
|
{
|
||||||
|
//FIXME: Check for error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer[readlen] = 0;
|
||||||
|
if (*(int*)buffer == -1)
|
||||||
|
{
|
||||||
|
if (buffer[4] == 'c')
|
||||||
|
{ //got a challenge
|
||||||
|
qtv->challenge = atoi(buffer+5);
|
||||||
|
sprintf(buffer, "connect %i %i %i \"%s\"", 28, qtv->qport, qtv->challenge, "\\*ver\\fteqtv\\name\\fteqtv\\spectator\\1");
|
||||||
|
Netchan_OutOfBand(qtv->cluster, qtv->sourcesock, qtv->serveraddress, strlen(buffer), buffer);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (buffer[4] == 'n')
|
||||||
|
{
|
||||||
|
Sys_Printf(qtv->cluster, "%s: %s", qtv->server, buffer+5);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (buffer[4] == 'j')
|
||||||
|
{
|
||||||
|
Netchan_Setup(qtv->sourcesock, &qtv->netchan, qtv->serveraddress, qtv->qport, true);
|
||||||
|
|
||||||
|
qtv->trackplayer = -1;
|
||||||
|
|
||||||
|
qtv->isconnected = true;
|
||||||
|
qtv->timeout = qtv->curtime + UDPTIMEOUT_LENGTH;
|
||||||
|
SendClientCommand(qtv, "new\n");
|
||||||
|
Sys_Printf(qtv->cluster, "Connected!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Sys_Printf(qtv->cluster, "%s: unrecognised connectionless packet:\n%s\n", qtv->server, buffer+4);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.cursize = readlen;
|
||||||
|
msg.data = buffer;
|
||||||
|
msg.maxsize = readlen;
|
||||||
|
qtv->timeout = qtv->curtime + UDPTIMEOUT_LENGTH;
|
||||||
|
if (!Netchan_Process(&qtv->netchan, &msg))
|
||||||
|
continue;
|
||||||
|
ParseMessage(qtv, msg.data + msg.readpos, msg.cursize - msg.readpos, dem_all, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QTV_Run(sv_t *qtv)
|
void QTV_Run(sv_t *qtv)
|
||||||
|
@ -1212,6 +1353,12 @@ void QTV_Run(sv_t *qtv)
|
||||||
int oldcurtime;
|
int oldcurtime;
|
||||||
int packettime;
|
int packettime;
|
||||||
|
|
||||||
|
if (qtv->disconnectwhennooneiswatching && qtv->numviewers == 0)
|
||||||
|
{
|
||||||
|
QTV_Shutdown(qtv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//we will read out as many packets as we can until we're up to date
|
//we will read out as many packets as we can until we're up to date
|
||||||
//note: this can cause real issues when we're overloaded for any length of time
|
//note: this can cause real issues when we're overloaded for any length of time
|
||||||
|
@ -1235,9 +1382,51 @@ void QTV_Run(sv_t *qtv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (qtv->usequkeworldprotocols)
|
||||||
|
{
|
||||||
|
if (!qtv->isconnected && (qtv->curtime >= qtv->nextconnectattempt || qtv->curtime < qtv->nextconnectattempt - UDPRECONNECT_TIME*2))
|
||||||
|
{
|
||||||
|
Netchan_OutOfBand(qtv->cluster, qtv->sourcesock, qtv->serveraddress, 12, "getchallenge");
|
||||||
|
qtv->nextconnectattempt = qtv->curtime + UDPRECONNECT_TIME;
|
||||||
|
}
|
||||||
|
QTV_ParseQWStream(qtv);
|
||||||
|
|
||||||
|
if (qtv->isconnected)
|
||||||
|
{
|
||||||
|
char buffer[64];
|
||||||
|
netmsg_t msg;
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.data = buffer;
|
||||||
|
msg.maxsize = sizeof(buffer);
|
||||||
|
|
||||||
|
if (qtv->curtime >= qtv->timeout || qtv->curtime < qtv->timeout - UDPTIMEOUT_LENGTH*2)
|
||||||
|
{
|
||||||
|
Sys_Printf(qtv->cluster, "Timeout\n");
|
||||||
|
qtv->isconnected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtv->curtime >= qtv->nextsendpings || qtv->curtime < qtv->nextsendpings - PINGSINTERVAL_TIME*2)
|
||||||
|
{
|
||||||
|
qtv->nextsendpings = qtv->curtime + PINGSINTERVAL_TIME;
|
||||||
|
SendClientCommand(qtv, "pings\n");
|
||||||
|
}
|
||||||
|
WriteByte(&msg, clc_tmove);
|
||||||
|
WriteShort(&msg, qtv->players[qtv->trackplayer].current.origin[0]);
|
||||||
|
WriteShort(&msg, qtv->players[qtv->trackplayer].current.origin[1]);
|
||||||
|
WriteShort(&msg, qtv->players[qtv->trackplayer].current.origin[2]);
|
||||||
|
|
||||||
|
Netchan_Transmit(qtv->cluster, &qtv->netchan, msg.cursize, msg.data);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (qtv->sourcesock == INVALID_SOCKET && !qtv->file)
|
if (qtv->sourcesock == INVALID_SOCKET && !qtv->file)
|
||||||
{
|
{
|
||||||
if (qtv->curtime >= qtv->nextconnectattemp || qtv->curtime < qtv->nextconnectattemp - RECONNECT_TIME*2)
|
if (qtv->curtime >= qtv->nextconnectattempt || qtv->curtime < qtv->nextconnectattempt - RECONNECT_TIME*2)
|
||||||
if (!QTV_Connect(qtv, qtv->server))
|
if (!QTV_Connect(qtv, qtv->server))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1380,7 +1569,7 @@ void QTV_Run(sv_t *qtv)
|
||||||
|
|
||||||
void Cluster_Run(cluster_t *cluster)
|
void Cluster_Run(cluster_t *cluster)
|
||||||
{
|
{
|
||||||
sv_t *sv;
|
sv_t *sv, *old;
|
||||||
|
|
||||||
int m;
|
int m;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
|
@ -1394,17 +1583,17 @@ void Cluster_Run(cluster_t *cluster)
|
||||||
if (cluster->qwdsocket >= m)
|
if (cluster->qwdsocket >= m)
|
||||||
m = cluster->qwdsocket+1;
|
m = cluster->qwdsocket+1;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
for (sv = cluster->servers; sv; sv = sv->next)
|
for (sv = cluster->servers; sv; sv = sv->next)
|
||||||
{
|
{
|
||||||
if (sv->sourcesock != INVALID_SOCKET)
|
if (sv->usequkeworldprotocols && sv->sourcesock != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
FD_SET(sv->sourcesock, &socketset);
|
FD_SET(sv->sourcesock, &socketset);
|
||||||
if (sv->sourcesock >= m)
|
if (sv->sourcesock >= m)
|
||||||
m = sv->sourcesock+1;
|
m = sv->sourcesock+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#ifndef STDIN
|
#ifndef STDIN
|
||||||
#define STDIN 0
|
#define STDIN 0
|
||||||
|
@ -1491,17 +1680,21 @@ void Cluster_Run(cluster_t *cluster)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (sv = cluster->servers; sv; sv = sv->next)
|
for (sv = cluster->servers; sv; )
|
||||||
{
|
{
|
||||||
QTV_Run(sv);
|
old = sv;
|
||||||
|
sv = sv->next;
|
||||||
|
QTV_Run(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
QW_UpdateUDPStuff(cluster);
|
QW_UpdateUDPStuff(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force)
|
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose)
|
||||||
{
|
{
|
||||||
sv_t *qtv = malloc(sizeof(sv_t));
|
sv_t *qtv = malloc(sizeof(sv_t));
|
||||||
|
if (!qtv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
memset(qtv, 0, sizeof(*qtv));
|
memset(qtv, 0, sizeof(*qtv));
|
||||||
//set up a default config
|
//set up a default config
|
||||||
|
@ -1510,6 +1703,8 @@ sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force)
|
||||||
|
|
||||||
qtv->listenmvd = INVALID_SOCKET;
|
qtv->listenmvd = INVALID_SOCKET;
|
||||||
qtv->sourcesock = INVALID_SOCKET;
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
|
qtv->disconnectwhennooneiswatching = autoclose;
|
||||||
|
qtv->parsingconnectiondata = true;
|
||||||
|
|
||||||
qtv->cluster = cluster;
|
qtv->cluster = cluster;
|
||||||
qtv->next = cluster->servers;
|
qtv->next = cluster->servers;
|
||||||
|
|
Loading…
Reference in a new issue