mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 21:31:37 +00:00
Corrupted the QTV proxy.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2189 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
b12ead1a7d
commit
aaef149474
8 changed files with 826 additions and 185 deletions
12
fteqtv/bsp.c
12
fteqtv/bsp.c
|
@ -231,13 +231,23 @@ bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
|
|||
|
||||
|
||||
header = (dheader_t*)data;
|
||||
if (data[0] != 29)
|
||||
if (size < sizeof(dheader_t) || data[0] != 29)
|
||||
{
|
||||
free(data);
|
||||
Sys_Printf(cluster, "BSP not version 29\n", bspname, gamedir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < HEADER_LUMPS; i++)
|
||||
{
|
||||
if (LittleLong(header->lumps[i].fileofs) + LittleLong(header->lumps[i].filelen) > size)
|
||||
{
|
||||
free(data);
|
||||
Sys_Printf(cluster, "BSP appears truncated\n", bspname, gamedir);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
planes = (dplane_t*)(data+LittleLong(header->lumps[LUMP_PLANES].fileofs));
|
||||
nodes = (dnode_t*)(data+LittleLong(header->lumps[LUMP_NODES].fileofs));
|
||||
leaf = (dleaf_t*)(data+LittleLong(header->lumps[LUMP_LEAFS].fileofs));
|
||||
|
|
|
@ -31,7 +31,7 @@ void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, net
|
|||
ret = sendto(sock, data, length, 0, (struct sockaddr *)adr, sizeof(struct sockaddr_in));
|
||||
if (ret < 0)
|
||||
{
|
||||
Sys_Printf(cluster, "udp send error\n");
|
||||
Sys_Printf(cluster, "udp send error %i\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
203
fteqtv/parse.c
203
fteqtv/parse.c
|
@ -218,6 +218,8 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
|||
|
||||
tv->clservercount = ReadLong(m); //we don't care about server's servercount, it's all reliable data anyway.
|
||||
|
||||
tv->trackplayer = -1;
|
||||
|
||||
ReadString(m, tv->gamedir, sizeof(tv->gamedir));
|
||||
|
||||
if (tv->usequkeworldprotocols)
|
||||
|
@ -265,8 +267,10 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
|||
|
||||
if (tv->usequkeworldprotocols)
|
||||
{
|
||||
tv->netchan.message.cursize = 0; //mvdsv sucks
|
||||
SendClientCommand(tv, "soundlist %i 0\n", tv->clservercount);
|
||||
}
|
||||
strcpy(tv->status, "Receiving soundlist\n");
|
||||
}
|
||||
|
||||
static void ParseCDTrack(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
||||
|
@ -284,13 +288,15 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
|||
qboolean fromproxy;
|
||||
|
||||
ReadString(m, text, sizeof(text));
|
||||
Sys_Printf(tv->cluster, "stuffcmd: %s", text);
|
||||
// Sys_Printf(tv->cluster, "stuffcmd: %s", text);
|
||||
|
||||
if (!strcmp(text, "skins\n"))
|
||||
{
|
||||
const char newcmd[10] = {svc_stufftext, 'c', 'm', 'd', ' ', 'n','e','w','\n','\0'};
|
||||
tv->parsingconnectiondata = false;
|
||||
|
||||
strcpy(tv->status, "On server\n");
|
||||
|
||||
for (v = tv->cluster->viewers; v; v = v->next)
|
||||
{
|
||||
if (v->server == tv)
|
||||
|
@ -353,8 +359,39 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
|||
SendClientCommand(tv, "new\n");
|
||||
return;
|
||||
}
|
||||
else if (!strncmp(text, "packet ", 7))
|
||||
{
|
||||
if(tv->usequkeworldprotocols)
|
||||
{//eeeevil hack
|
||||
|
||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||
#define ARG_LEN 256
|
||||
char *ptr;
|
||||
char arg[3][ARG_LEN];
|
||||
netadr_t adr;
|
||||
ptr = text;
|
||||
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);
|
||||
Netchan_OutOfBand(tv->cluster, tv->sourcesock, adr, strlen(arg[2]), arg[2]);
|
||||
|
||||
//this is an evil hack
|
||||
SendClientCommand(tv, "new\n");
|
||||
return;
|
||||
}
|
||||
tv->drop = true; //this shouldn't ever happen
|
||||
return;
|
||||
}
|
||||
else if (tv->usequkeworldprotocols && !strncmp(text, "setinfo ", 8))
|
||||
{
|
||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||
SendClientCommand(tv, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseSetInfo(sv_t *tv, netmsg_t *m)
|
||||
|
@ -577,7 +614,9 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if (flags & (PF_VELOCITY1<<i) )
|
||||
ReadShort(m);
|
||||
tv->players[num].current.velocity[i] = ReadShort(m);
|
||||
else
|
||||
tv->players[num].current.velocity[i] = 0;
|
||||
}
|
||||
|
||||
if (flags & PF_MODEL)
|
||||
|
@ -600,7 +639,7 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m, qboolean clearoldplayers)
|
|||
else
|
||||
tv->players[num].current.weaponframe = 0;
|
||||
|
||||
tv->players[num].active = (num != tv->thisplayer);
|
||||
tv->players[num].active = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -660,6 +699,8 @@ static void ParsePacketEntities(sv_t *tv, netmsg_t *m)
|
|||
|
||||
viewer_t *v;
|
||||
|
||||
tv->nailcount = 0;
|
||||
|
||||
tv->physicstime = tv->parsetime;
|
||||
|
||||
if (tv->cluster->chokeonnotupdated)
|
||||
|
@ -750,12 +791,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)
|
||||
{
|
||||
int best;
|
||||
int pnum;
|
||||
int frags;
|
||||
char buffer[64];
|
||||
pnum = ReadByte(m);
|
||||
frags = ReadShort(m);
|
||||
frags = (signed short)ReadShort(m);
|
||||
|
||||
if (pnum < MAX_CLIENTS)
|
||||
tv->players[pnum].frags = frags;
|
||||
|
@ -763,26 +802,6 @@ static void ParseUpdateFrags(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
|||
Sys_Printf(tv->cluster, "svc_updatefrags: invalid player number\n");
|
||||
|
||||
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)
|
||||
|
@ -1045,20 +1064,79 @@ void ParseLightstyle(sv_t *tv, netmsg_t *m)
|
|||
void ParseNails(sv_t *tv, netmsg_t *m, qboolean nails2)
|
||||
{
|
||||
int count;
|
||||
int nailnum;
|
||||
int i;
|
||||
unsigned char bits[6];
|
||||
count = (unsigned char)ReadByte(m);
|
||||
while(count > sizeof(tv->nails) / sizeof(tv->nails[0]))
|
||||
{
|
||||
count--;
|
||||
if (nails2)
|
||||
ReadByte(m);
|
||||
for (i = 0; i < 6; i++)
|
||||
ReadByte(m);
|
||||
}
|
||||
|
||||
tv->nailcount = count;
|
||||
while(count-- > 0)
|
||||
{
|
||||
if (nails2)
|
||||
nailnum = ReadByte(m);
|
||||
tv->nails[count].number = ReadByte(m);
|
||||
else
|
||||
nailnum = count;
|
||||
tv->nails[count].number = count;
|
||||
for (i = 0; i < 6; i++)
|
||||
bits[i] = ReadByte(m);
|
||||
tv->nails[count].bits[i] = ReadByte(m);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseDownload(sv_t *tv, netmsg_t *m)
|
||||
{
|
||||
int size, b;
|
||||
unsigned int percent;
|
||||
char buffer[2048];
|
||||
|
||||
size = ReadShort(m);
|
||||
percent = ReadByte(m);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
Sys_Printf(tv->cluster, "Downloading failed\n");
|
||||
if (tv->file)
|
||||
fclose(tv->file);
|
||||
tv->file = NULL;
|
||||
tv->drop = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (b = 0; b < size; b++)
|
||||
buffer[b] = ReadByte(m);
|
||||
|
||||
if (!tv->file)
|
||||
{
|
||||
Sys_Printf(tv->cluster, "Not downloading anything\n");
|
||||
tv->drop = true;
|
||||
return;
|
||||
}
|
||||
fwrite(buffer, 1, size, tv->file);
|
||||
|
||||
if (percent == 100)
|
||||
{
|
||||
fclose(tv->file);
|
||||
tv->file = NULL;
|
||||
Sys_Printf(tv->cluster, "Download complete\n");
|
||||
|
||||
tv->bsp = BSP_LoadModel(tv->cluster, tv->gamedir, tv->modellist[1].name);
|
||||
if (!tv->bsp)
|
||||
tv->drop = true;
|
||||
else
|
||||
{
|
||||
SendClientCommand(tv, "prespawn %i 0 %i\n", tv->clservercount, LittleLong(BSP_Checksum(tv->bsp)));
|
||||
strcpy(tv->status, "Prespawning\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(tv->status, sizeof(tv->status), "Downloading map, %i%%\n", percent);
|
||||
SendClientCommand(tv, "nextdl\n");
|
||||
}
|
||||
//qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8
|
||||
}
|
||||
|
||||
void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
||||
|
@ -1118,10 +1196,14 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
break;
|
||||
|
||||
case svc_setangle:
|
||||
if (!tv->usequkeworldprotocols)
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
|
||||
if (tv->usequkeworldprotocols && tv->controller)
|
||||
SendBufferToViewer(tv->controller, buf.data+buf.startpos, buf.readpos - buf.startpos, true);
|
||||
break;
|
||||
|
||||
case svc_serverdata:
|
||||
|
@ -1139,7 +1221,18 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
//#define svc_clientdata 15 // <shortbits + data>
|
||||
//#define svc_stopsound 16 // <see code>
|
||||
//#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
|
||||
//#define svc_particle 18 // [vec3] <variable>
|
||||
|
||||
case svc_particle:
|
||||
ReadShort(&buf);
|
||||
ReadShort(&buf);
|
||||
ReadShort(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
ReadByte(&buf);
|
||||
Multicast(tv, buf.data+buf.startpos, buf.readpos - buf.startpos, dem_read, (unsigned)-1);
|
||||
break;
|
||||
case svc_damage:
|
||||
ParseDamage(tv, &buf, to, mask);
|
||||
break;
|
||||
|
@ -1214,7 +1307,9 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
ParseUpdateUserinfo(tv, &buf, to, mask);
|
||||
break;
|
||||
|
||||
//#define svc_download 41 // [short] size [size bytes]
|
||||
case svc_download: // [short] size [size bytes]
|
||||
ParseDownload(tv, &buf);
|
||||
break;
|
||||
case svc_playerinfo:
|
||||
ParsePlayerInfo(tv, &buf, clearoldplayers);
|
||||
clearoldplayers = false;
|
||||
|
@ -1233,7 +1328,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
if (tv->bsp)
|
||||
BSP_Free(tv->bsp);
|
||||
|
||||
if (tv->cluster->nobsp)
|
||||
if (tv->cluster->nobsp && !tv->usequkeworldprotocols)
|
||||
tv->bsp = NULL;
|
||||
else
|
||||
tv->bsp = BSP_LoadModel(tv->cluster, tv->gamedir, tv->modellist[1].name);
|
||||
|
@ -1245,17 +1340,42 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
break;
|
||||
tv->numinlines = j;
|
||||
}
|
||||
strcpy(tv->status, "Prespawning\n");
|
||||
}
|
||||
if (tv->usequkeworldprotocols)
|
||||
{
|
||||
if (i)
|
||||
SendClientCommand(tv, "modellist %i %i\n", tv->clservercount, i);
|
||||
else if (!tv->bsp)
|
||||
{
|
||||
if (tv->file)
|
||||
{
|
||||
fclose(tv->file);
|
||||
unlink(tv->downloadname);
|
||||
Sys_Printf(tv->cluster, "Was already downloading %s\nOld download canceled\n");
|
||||
tv->file = NULL;
|
||||
}
|
||||
snprintf(tv->downloadname, sizeof(tv->downloadname), "%s/%s", (tv->gamedir&&*tv->gamedir)?tv->gamedir:"qw", tv->modellist[1].name, sizeof(tv->downloadname));
|
||||
tv->file = fopen(tv->downloadname, "wb");
|
||||
if (!tv->file)
|
||||
tv->drop = true;
|
||||
else
|
||||
{
|
||||
strcpy(tv->status, "Downloading map\n");
|
||||
Sys_Printf(tv->cluster, "Attempting download of %s\n", tv->downloadname);
|
||||
SendClientCommand(tv, "download %s\n", tv->modellist[1].name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SendClientCommand(tv, "prespawn %i 0 %i\n", tv->clservercount, LittleLong(BSP_Checksum(tv->bsp)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case svc_soundlist:
|
||||
i = ParseList(tv, &buf, tv->soundlist, to, mask);
|
||||
if (!i)
|
||||
strcpy(tv->status, "Receiving modellist\n");
|
||||
if (tv->usequkeworldprotocols)
|
||||
{
|
||||
if (i)
|
||||
|
@ -1274,8 +1394,13 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask)
|
|||
break;
|
||||
//#define svc_maxspeed 49 // maxspeed change, for prediction
|
||||
case svc_entgravity: // gravity change, for prediction
|
||||
ReadFloat(&buf);
|
||||
break;
|
||||
ReadFloat(&buf);
|
||||
Multicast(tv, buf.data+buf.startpos, buf.readpos - buf.startpos, to, mask);
|
||||
break;
|
||||
case svc_maxspeed:
|
||||
ReadFloat(&buf);
|
||||
Multicast(tv, buf.data+buf.startpos, buf.readpos - buf.startpos, to, mask);
|
||||
break;
|
||||
case svc_setinfo:
|
||||
ParseSetInfo(tv, &buf);
|
||||
break;
|
||||
|
|
52
fteqtv/qtv.h
52
fteqtv/qtv.h
|
@ -46,6 +46,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#pragma comment (lib, "wsock32.lib")
|
||||
#define qerrno WSAGetLastError()
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//okay, so warnings are here to help... they're ugly though.
|
||||
|
@ -205,6 +206,7 @@ typedef struct {
|
|||
unsigned char modelindex;
|
||||
unsigned char skinnum;
|
||||
short origin[3];
|
||||
short velocity[3];
|
||||
unsigned short angles[3];
|
||||
unsigned char effects;
|
||||
unsigned char weaponframe;
|
||||
|
@ -234,6 +236,15 @@ typedef struct {
|
|||
int numents;
|
||||
} packet_entities_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char msec;
|
||||
unsigned short angles[3];
|
||||
short forwardmove, sidemove, upmove;
|
||||
unsigned char buttons;
|
||||
unsigned char impulse;
|
||||
} usercmd_t;
|
||||
extern const usercmd_t nullcmd;
|
||||
|
||||
#define MAX_BACK_BUFFERS 16
|
||||
typedef struct sv_s sv_t;
|
||||
typedef struct cluster_s cluster_t;
|
||||
|
@ -251,13 +262,18 @@ typedef struct viewer_s {
|
|||
int backbuffered;
|
||||
|
||||
unsigned int currentstats[MAX_STATS];
|
||||
unsigned int trackplayer;
|
||||
int trackplayer;
|
||||
int thisplayer;
|
||||
|
||||
packet_entities_t frame[ENTITY_FRAMES];
|
||||
|
||||
struct viewer_s *next;
|
||||
|
||||
char name[32];
|
||||
char userinfo[256];
|
||||
|
||||
int lost; //packets
|
||||
usercmd_t ucmds[3];
|
||||
|
||||
|
||||
int settime; //the time that we last told the client.
|
||||
|
@ -307,12 +323,9 @@ typedef struct {
|
|||
} entity_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char msec;
|
||||
unsigned short angles[3];
|
||||
short forwardmove, sidemove, upmove;
|
||||
unsigned char buttons;
|
||||
unsigned char impulse;
|
||||
} usercmd_t;
|
||||
unsigned char number;
|
||||
char bits[6];
|
||||
} nail_t;
|
||||
|
||||
struct sv_s {
|
||||
netadr_t serveraddress;
|
||||
|
@ -355,17 +368,27 @@ struct sv_s {
|
|||
int modelindex_spike; // qw is wierd.
|
||||
int modelindex_player; // qw is wierd.
|
||||
|
||||
FILE *downloadfile;
|
||||
char downloadname[256];
|
||||
|
||||
char status[64];
|
||||
|
||||
nail_t nails[32];
|
||||
int nailcount;
|
||||
|
||||
qboolean usequkeworldprotocols;
|
||||
int challenge;
|
||||
unsigned short qport;
|
||||
int isconnected;
|
||||
int clservercount;
|
||||
unsigned int nextsendpings;
|
||||
unsigned int trackplayer;
|
||||
int trackplayer;
|
||||
int thisplayer;
|
||||
unsigned int timeout;
|
||||
qboolean ispaused;
|
||||
unsigned int packetratelimiter;
|
||||
viewer_t *controller;
|
||||
boolean maysend;
|
||||
|
||||
FILE *file;
|
||||
unsigned int filelength;
|
||||
|
@ -388,11 +411,10 @@ struct sv_s {
|
|||
|
||||
|
||||
|
||||
qboolean drop;
|
||||
qboolean disconnectwhennooneiswatching;
|
||||
unsigned int numviewers;
|
||||
|
||||
|
||||
|
||||
cluster_t *cluster;
|
||||
sv_t *next; //next proxy->server connection
|
||||
|
||||
|
@ -484,7 +506,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen);
|
|||
//#define svc_clientdata 15 // <shortbits + data>
|
||||
//#define svc_stopsound 16 // <see code>
|
||||
//#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
|
||||
//#define svc_particle 18 // [vec3] <variable>
|
||||
#define svc_particle 18 // [vec3] <variable>
|
||||
#define svc_damage 19
|
||||
|
||||
#define svc_spawnstatic 20
|
||||
|
@ -531,7 +553,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen);
|
|||
#define svc_soundlist 46 // [strings]
|
||||
#define svc_packetentities 47 // [...]
|
||||
#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_setinfo 51 // setinfo on a client
|
||||
#define svc_serverinfo 52 // serverinfo
|
||||
|
@ -623,7 +645,7 @@ unsigned int Sys_Milliseconds(void);
|
|||
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);
|
||||
qboolean NET_StringToAddr (char *s, netadr_t *sadr, int defaultport);
|
||||
|
||||
void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean reliable);
|
||||
void QW_PrintfToViewer(viewer_t *v, char *format, ...);
|
||||
|
@ -637,7 +659,7 @@ qboolean Net_CompareAddress(netadr_t *s1, netadr_t *s2, int qp1, int qp2);
|
|||
qboolean Netchan_Process (netchan_t *chan, netmsg_t *msg);
|
||||
void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const unsigned char *data);
|
||||
int SendList(sv_t *qtv, int first, const filename_t *list, int svc, netmsg_t *msg);
|
||||
int Prespawn(sv_t *qtv, int curmsgsize, netmsg_t *msg, int bufnum);
|
||||
int Prespawn(sv_t *qtv, int curmsgsize, netmsg_t *msg, int bufnum, int thisplayer);
|
||||
|
||||
bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname);
|
||||
void BSP_Free(bsp_t *bsp);
|
||||
|
@ -659,7 +681,7 @@ int vsnprintf(char *buffer, int buffersize, char *format, va_list argptr);
|
|||
#endif
|
||||
|
||||
qboolean Net_FileProxy(sv_t *qtv, char *filename);
|
||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose);
|
||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose, qboolean noduplicates);
|
||||
SOCKET Net_MVDListen(int port);
|
||||
qboolean Net_StopFileProxy(sv_t *qtv);
|
||||
|
||||
|
|
|
@ -90,6 +90,10 @@ SOURCE=.\bsp.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdfour.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
488
fteqtv/qw.c
488
fteqtv/qw.c
|
@ -20,7 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "qtv.h"
|
||||
|
||||
#define MENU_NONE 0
|
||||
#define MENU_SERVERS 1
|
||||
#define MENU_ADMIN 2
|
||||
#define MENU_ADMINSERVER 3
|
||||
|
||||
void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum);
|
||||
void QW_SetMenu(viewer_t *v, int menunum);
|
||||
|
||||
#ifdef _WIN32
|
||||
int snprintf(char *buffer, int buffersize, char *format, ...)
|
||||
|
@ -230,7 +236,7 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount)
|
|||
if (mvd)
|
||||
WriteFloat(msg, 0);
|
||||
else
|
||||
WriteByte(msg, MAX_CLIENTS-1);
|
||||
WriteByte(msg, tv->thisplayer);
|
||||
WriteString(msg, tv->mapname);
|
||||
|
||||
|
||||
|
@ -261,6 +267,10 @@ void SendServerData(sv_t *tv, viewer_t *viewer)
|
|||
char buffer[1024];
|
||||
InitNetMsg(&msg, buffer, sizeof(buffer));
|
||||
|
||||
if (tv && (tv->controller == viewer || !tv->controller))
|
||||
viewer->thisplayer = tv->thisplayer;
|
||||
else
|
||||
viewer->thisplayer = MAX_CLIENTS-1;
|
||||
BuildServerData(tv, &msg, false, viewer->servercount);
|
||||
|
||||
SendBufferToViewer(viewer, msg.data, msg.cursize, true);
|
||||
|
@ -270,20 +280,42 @@ void SendServerData(sv_t *tv, viewer_t *viewer)
|
|||
memset(viewer->currentstats, 0, sizeof(viewer->currentstats));
|
||||
}
|
||||
|
||||
int SendCurrentUserinfos(sv_t *tv, int cursize, netmsg_t *msg, int i)
|
||||
int SendCurrentUserinfos(sv_t *tv, int cursize, netmsg_t *msg, int i, int thisplayer)
|
||||
{
|
||||
if (i < 0)
|
||||
return i;
|
||||
if (i >= MAX_CLIENTS)
|
||||
return i;
|
||||
|
||||
WriteByte(msg, svc_updateuserinfo);
|
||||
WriteByte(msg, MAX_CLIENTS-1);
|
||||
WriteLong(msg, MAX_CLIENTS-1);
|
||||
WriteString(msg, "\\*spectator\\1\\name\\YOU!");
|
||||
|
||||
for (; i < MAX_CLIENTS-1; i++)
|
||||
for (; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (i == thisplayer && !tv->controller)
|
||||
{
|
||||
WriteByte(msg, svc_updateuserinfo);
|
||||
WriteByte(msg, i);
|
||||
WriteLong(msg, i);
|
||||
WriteString2(msg, "\\*spectator\\1\\name\\");
|
||||
if (!tv || !*tv->hostname)
|
||||
WriteString(msg, "FTEQTV");
|
||||
else
|
||||
WriteString(msg, tv->hostname);
|
||||
|
||||
WriteByte(msg, svc_updatefrags);
|
||||
WriteByte(msg, i);
|
||||
WriteShort(msg, 9999);
|
||||
|
||||
WriteByte(msg, svc_updateping);
|
||||
WriteByte(msg, i);
|
||||
WriteShort(msg, 0);
|
||||
|
||||
WriteByte(msg, svc_updatepl);
|
||||
WriteByte(msg, i);
|
||||
WriteByte(msg, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (!tv)
|
||||
continue;
|
||||
if (msg->cursize+cursize+strlen(tv->players[i].userinfo) > 768)
|
||||
{
|
||||
return i;
|
||||
|
@ -440,7 +472,10 @@ void QW_SetViewersServer(viewer_t *viewer, sv_t *sv)
|
|||
viewer->server = sv;
|
||||
if (viewer->server)
|
||||
viewer->server->numviewers++;
|
||||
QW_StuffcmdToViewer(viewer, "reconnect\n");
|
||||
if (!sv || !sv->parsingconnectiondata)
|
||||
{
|
||||
QW_StuffcmdToViewer(viewer, "cmd new\n");
|
||||
}
|
||||
viewer->servercount++;
|
||||
viewer->origin[0] = 0;
|
||||
viewer->origin[1] = 0;
|
||||
|
@ -509,19 +544,74 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
|||
viewer->server->numviewers++;
|
||||
|
||||
if (!initialserver)
|
||||
viewer->menunum = 1;
|
||||
{
|
||||
QW_SetMenu(viewer, MENU_SERVERS);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewer->menunum = -1;
|
||||
QW_SetMenu(viewer, MENU_NONE);
|
||||
}
|
||||
|
||||
cluster->numviewers++;
|
||||
|
||||
Info_ValueForKey(infostring, "name", viewer->name, sizeof(viewer->name));
|
||||
strncpy(viewer->userinfo, infostring, sizeof(viewer->userinfo)-1);
|
||||
|
||||
Netchan_OutOfBandPrint(cluster, cluster->qwdsocket, *addr, "j");
|
||||
|
||||
QW_PrintfToViewer(viewer, "Welcome to FTEQTV\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias admin \"cmd admin\"\n");
|
||||
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:up\" \"say proxy:menu up\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:down\" \"say proxy:menu down\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:right\" \"say proxy:menu right\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:left\" \"say proxy:menu left\"\n");
|
||||
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:select\" \"say proxy:menu select\"\n");
|
||||
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:home\" \"say proxy:menu home\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:end\" \"say proxy:menu end\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:menu\" \"say proxy:menu\"\n");
|
||||
QW_StuffcmdToViewer(viewer, "alias \"proxy:backspace\" \"say proxy:menu backspace\"\n");
|
||||
|
||||
QW_PrintfToViewer(viewer, "Type admin for the admin menu\n");
|
||||
|
||||
// if
|
||||
}
|
||||
|
||||
void QW_SetMenu(viewer_t *v, int menunum)
|
||||
{
|
||||
if ((v->menunum==MENU_NONE) != (menunum==MENU_NONE))
|
||||
{
|
||||
if (menunum != MENU_NONE)
|
||||
{
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxfwd\" \"proxy:up\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxback\" \"proxy:down\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxleft\" \"proxy:left\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxright\" \"proxy:right\"\n");
|
||||
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxfwd\" \" \"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxback\" \" \"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxleft\" \" \"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxright\" \" \"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxfwd\" \"+forward\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxback\" \"+back\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxleft\" \"+moveleft\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"+proxright\" \"+moveright\"\n");
|
||||
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxfwd\" \"-forward\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxback\" \"-back\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxleft\" \"-moveleft\"\n");
|
||||
QW_StuffcmdToViewer(v, "alias \"-proxright\" \"-moveright\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
v->menunum = menunum;
|
||||
v->menuop = 0;
|
||||
}
|
||||
|
||||
void QTV_Rcon(cluster_t *cluster, char *message, netadr_t *from)
|
||||
|
@ -570,8 +660,10 @@ void QTV_Status(cluster_t *cluster, netadr_t *from)
|
|||
WriteString2(&msg, sv->serverinfo);
|
||||
WriteString2(&msg, "\n");
|
||||
|
||||
for (i = 0;i < MAX_CLIENTS-1; i++)
|
||||
for (i = 0;i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (i == sv->thisplayer)
|
||||
continue;
|
||||
if (!sv->players[i].active)
|
||||
continue;
|
||||
//userid
|
||||
|
@ -852,10 +944,59 @@ static float InterpolateAngle(float current, float ideal, float fraction)
|
|||
return current + fraction * move;
|
||||
}
|
||||
|
||||
void SendLocalPlayerState(sv_t *tv, viewer_t *v, int playernum, netmsg_t *msg)
|
||||
{
|
||||
int flags;
|
||||
int j;
|
||||
|
||||
WriteByte(msg, svc_playerinfo);
|
||||
WriteByte(msg, playernum);
|
||||
|
||||
if (tv && tv->controller == v)
|
||||
{
|
||||
v->trackplayer = tv->thisplayer;
|
||||
flags = 0;
|
||||
if (tv->players[tv->thisplayer].current.weaponframe)
|
||||
flags |= PF_WEAPONFRAME;
|
||||
if (tv->players[tv->thisplayer].current.effects)
|
||||
flags |= PF_EFFECTS;
|
||||
for (j=0 ; j<3 ; j++)
|
||||
if (tv->players[tv->thisplayer].current.velocity[j])
|
||||
flags |= (PF_VELOCITY1<<j);
|
||||
|
||||
WriteShort(msg, flags);
|
||||
WriteShort(msg, tv->players[tv->thisplayer].current.origin[0]);
|
||||
WriteShort(msg, tv->players[tv->thisplayer].current.origin[1]);
|
||||
WriteShort(msg, tv->players[tv->thisplayer].current.origin[2]);
|
||||
WriteByte(msg, tv->players[tv->thisplayer].current.frame);
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
if (flags & (PF_VELOCITY1<<j) )
|
||||
WriteShort (msg, tv->players[tv->thisplayer].current.velocity[j]);
|
||||
|
||||
if (flags & PF_MODEL)
|
||||
WriteByte(msg, tv->players[tv->thisplayer].current.modelindex);
|
||||
if (flags & PF_SKINNUM)
|
||||
WriteByte(msg, tv->players[tv->thisplayer].current.skinnum);
|
||||
if (flags & PF_EFFECTS)
|
||||
WriteByte(msg, tv->players[tv->thisplayer].current.effects);
|
||||
if (flags & PF_WEAPONFRAME)
|
||||
WriteByte(msg, tv->players[tv->thisplayer].current.weaponframe);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteShort(msg, 0);
|
||||
WriteShort(msg, v->origin[0]*8);
|
||||
WriteShort(msg, v->origin[1]*8);
|
||||
WriteShort(msg, v->origin[2]*8);
|
||||
WriteByte(msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
||||
{
|
||||
packet_entities_t *e;
|
||||
int i;
|
||||
int i,j;
|
||||
usercmd_t to;
|
||||
unsigned short flags;
|
||||
short interp;
|
||||
|
@ -864,7 +1005,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
|
||||
memset(&to, 0, sizeof(to));
|
||||
|
||||
if (v->server)
|
||||
if (tv)
|
||||
{
|
||||
if (tv->physicstime != v->settime && tv->cluster->chokeonnotupdated)
|
||||
{
|
||||
|
@ -883,8 +1024,16 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
if (lerp > 1)
|
||||
lerp = 1;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS-1; i++)
|
||||
if (tv->controller == v)
|
||||
lerp = 1;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (i == v->thisplayer)
|
||||
{
|
||||
SendLocalPlayerState(tv, v, i, msg);
|
||||
continue;
|
||||
}
|
||||
if (!tv->players[i].active)
|
||||
continue;
|
||||
|
||||
|
@ -935,25 +1084,14 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
else
|
||||
{
|
||||
lerp = 1;
|
||||
|
||||
SendLocalPlayerState(tv, v, v->thisplayer, msg);
|
||||
}
|
||||
|
||||
WriteByte(msg, svc_playerinfo);
|
||||
WriteByte(msg, MAX_CLIENTS-1);
|
||||
WriteShort(msg, 0);
|
||||
|
||||
WriteShort(msg, v->origin[0]*8);
|
||||
WriteShort(msg, v->origin[1]*8);
|
||||
WriteShort(msg, v->origin[2]*8);
|
||||
|
||||
WriteByte(msg, 0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
e = &v->frame[v->netchan.outgoing_sequence&(ENTITY_FRAMES-1)];
|
||||
e->numents = 0;
|
||||
if (v->server)
|
||||
if (tv)
|
||||
for (i = 0; i < tv->maxents; i++)
|
||||
{
|
||||
if (!tv->entity[i].current.modelindex)
|
||||
|
@ -979,6 +1117,21 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg)
|
|||
}
|
||||
|
||||
SV_EmitPacketEntities(tv, v, e, msg);
|
||||
|
||||
if (tv && tv->nailcount)
|
||||
{
|
||||
WriteByte(msg, svc_nails);
|
||||
WriteByte(msg, tv->nailcount);
|
||||
for (i = 0; i < tv->nailcount; i++)
|
||||
{
|
||||
WriteByte(msg, tv->nails[i].bits[0]);
|
||||
WriteByte(msg, tv->nails[i].bits[1]);
|
||||
WriteByte(msg, tv->nails[i].bits[2]);
|
||||
WriteByte(msg, tv->nails[i].bits[3]);
|
||||
WriteByte(msg, tv->nails[i].bits[4]);
|
||||
WriteByte(msg, tv->nails[i].bits[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateStats(sv_t *qtv, viewer_t *v)
|
||||
|
@ -992,7 +1145,9 @@ void UpdateStats(sv_t *qtv, viewer_t *v)
|
|||
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
|
||||
if (v->trackplayer < 0 || !qtv)
|
||||
if (qtv && qtv->controller == v)
|
||||
stats = qtv->players[qtv->thisplayer].stats;
|
||||
else if (v->trackplayer < 0 || !qtv)
|
||||
stats = nullstats;
|
||||
else
|
||||
stats = qtv->players[v->trackplayer].stats;
|
||||
|
@ -1021,12 +1176,12 @@ void UpdateStats(sv_t *qtv, viewer_t *v)
|
|||
}
|
||||
|
||||
//returns the next prespawn 'buffer' number to use, or -1 if no more
|
||||
int Prespawn(sv_t *qtv, int curmsgsize, netmsg_t *msg, int bufnum)
|
||||
int Prespawn(sv_t *qtv, int curmsgsize, netmsg_t *msg, int bufnum, int thisplayer)
|
||||
{
|
||||
int r, ni;
|
||||
r = bufnum;
|
||||
|
||||
ni = SendCurrentUserinfos(qtv, curmsgsize, msg, bufnum);
|
||||
ni = SendCurrentUserinfos(qtv, curmsgsize, msg, bufnum, thisplayer);
|
||||
r += ni - bufnum;
|
||||
bufnum = ni;
|
||||
bufnum -= MAX_CLIENTS;
|
||||
|
@ -1089,13 +1244,20 @@ void PMove(viewer_t *v, usercmd_t *cmd)
|
|||
{
|
||||
int i;
|
||||
float fwd[3], rgt[3], up[3];
|
||||
if (v->server && v->server->controller == v)
|
||||
{
|
||||
v->origin[0] = v->server->players[v->server->thisplayer].current.origin[0]/8.0f;
|
||||
v->origin[1] = v->server->players[v->server->thisplayer].current.origin[1]/8.0f;
|
||||
v->origin[2] = v->server->players[v->server->thisplayer].current.origin[2]/8.0f;
|
||||
return;
|
||||
}
|
||||
AngleVectors(cmd->angles, fwd, rgt, up);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
v->origin[i] += (cmd->forwardmove*fwd[i] + cmd->sidemove*rgt[i] + cmd->upmove*up[i])*(cmd->msec/1000.0f);
|
||||
}
|
||||
|
||||
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
||||
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean noupwards)
|
||||
{
|
||||
char buf[1024];
|
||||
netmsg_t msg;
|
||||
|
@ -1103,7 +1265,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
if (message[strlen(message)-1] == '\"')
|
||||
message[strlen(message)-1] = '\0';
|
||||
|
||||
if (*v->expectcommand && v->menunum)
|
||||
if (*v->expectcommand)
|
||||
{
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
if (!strcmp(v->expectcommand, "hostname"))
|
||||
|
@ -1122,7 +1284,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
else if (!strcmp(v->expectcommand, "addserver"))
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "tcp:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, false, false);
|
||||
if (qtv)
|
||||
{
|
||||
QW_SetViewersServer(v, qtv);
|
||||
|
@ -1135,7 +1297,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
{
|
||||
if (!strcmp(message, cluster->password))
|
||||
{
|
||||
v->menunum = 2;
|
||||
QW_SetMenu(v, MENU_ADMIN);
|
||||
v->isadmin = true;
|
||||
Sys_Printf(cluster, "Player %s logs in as admin\n", v->name);
|
||||
}
|
||||
|
@ -1148,7 +1310,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
else if (!strcmp(v->expectcommand, "adddemo"))
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "file:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, false, false);
|
||||
if (!qtv)
|
||||
QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message);
|
||||
else
|
||||
|
@ -1211,10 +1373,26 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
else
|
||||
message += 9;
|
||||
snprintf(buf, sizeof(buf), "udp:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, false);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true, true);
|
||||
if (qtv)
|
||||
{
|
||||
// QW_SetViewersServer(v, qtv);
|
||||
QW_SetMenu(v, MENU_NONE);
|
||||
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, ".join ", 6))
|
||||
{
|
||||
message += 6;
|
||||
snprintf(buf, sizeof(buf), "udp:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true, false);
|
||||
if (qtv)
|
||||
{
|
||||
QW_SetMenu(v, MENU_NONE);
|
||||
QW_SetViewersServer(v, qtv);
|
||||
qtv->controller = v;
|
||||
QW_PrintfToViewer(v, "Connected\n", message);
|
||||
}
|
||||
else
|
||||
|
@ -1224,9 +1402,10 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
{
|
||||
message += 5;
|
||||
snprintf(buf, sizeof(buf), "tcp:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true, true);
|
||||
if (qtv)
|
||||
{
|
||||
QW_SetMenu(v, MENU_NONE);
|
||||
QW_SetViewersServer(v, qtv);
|
||||
QW_PrintfToViewer(v, "Connected\n", message);
|
||||
}
|
||||
|
@ -1237,9 +1416,10 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
{
|
||||
message += 6;
|
||||
snprintf(buf, sizeof(buf), "file:%s", message);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true);
|
||||
qtv = QTV_NewServerConnection(cluster, buf, false, true, true);
|
||||
if (qtv)
|
||||
{
|
||||
QW_SetMenu(v, MENU_NONE);
|
||||
QW_SetViewersServer(v, qtv);
|
||||
QW_PrintfToViewer(v, "Connected\n", message);
|
||||
}
|
||||
|
@ -1248,6 +1428,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
}
|
||||
else if (!strncmp(message, ".disconnect", 11))
|
||||
{
|
||||
QW_SetMenu(v, MENU_SERVERS);
|
||||
QW_SetViewersServer(v, NULL);
|
||||
QW_PrintfToViewer(v, "Connected\n", message);
|
||||
}
|
||||
|
@ -1288,7 +1469,24 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
}
|
||||
else if (!strncmp(message, "proxy:menu", 10))
|
||||
{
|
||||
Menu_Enter(cluster, v, 0);
|
||||
if (v->menunum)
|
||||
Menu_Enter(cluster, v, 0);
|
||||
else
|
||||
QW_SetMenu(v, MENU_SERVERS);
|
||||
}
|
||||
else if (!strncmp(message, ".menu bind", 10) || !strncmp(message, "proxy:menu bindstd", 18))
|
||||
{
|
||||
QW_StuffcmdToViewer(v, "bind uparrow proxy:menu up\n");
|
||||
QW_StuffcmdToViewer(v, "bind downarrow proxy:menu down\n");
|
||||
QW_StuffcmdToViewer(v, "bind rightarrow proxy:menu right\n");
|
||||
QW_StuffcmdToViewer(v, "bind leftarrow proxy:menu left\n");
|
||||
|
||||
QW_StuffcmdToViewer(v, "bind enter proxy:menu select\n");
|
||||
|
||||
QW_StuffcmdToViewer(v, "bind home proxy:menu home\n");
|
||||
QW_StuffcmdToViewer(v, "bind end proxy:menu end\n");
|
||||
QW_StuffcmdToViewer(v, "bind pause proxy:menu\n");
|
||||
QW_StuffcmdToViewer(v, "bind backspace proxy:back up\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1297,8 +1495,13 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message)
|
|||
if (cluster->notalking)
|
||||
return;
|
||||
|
||||
if (qtv && qtv->usequkeworldprotocols)
|
||||
SendClientCommand(qtv, "say %s: %s\n", v->name, message);
|
||||
if (qtv && qtv->usequkeworldprotocols && !noupwards)
|
||||
{
|
||||
if (qtv->controller == v || !*v->name)
|
||||
SendClientCommand(qtv, "say %s\n", message);
|
||||
else
|
||||
SendClientCommand(qtv, "say %s: %s\n", v->name, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
@ -1352,7 +1555,6 @@ void QW_StuffcmdToViewer(viewer_t *v, char *format, ...)
|
|||
va_end (argptr);
|
||||
|
||||
buf[0] = svc_stufftext;
|
||||
printf("\"%s\"", buf);
|
||||
SendBufferToViewer(v, buf, strlen(buf)+1, true);
|
||||
}
|
||||
|
||||
|
@ -1362,7 +1564,7 @@ static const filename_t ConnectionlessSoundList[] = {{""}, {""}};
|
|||
|
||||
void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
||||
{
|
||||
usercmd_t oldest, oldcmd, newcmd;
|
||||
// usercmd_t oldest, oldcmd, newcmd;
|
||||
char buf[1024];
|
||||
netmsg_t msg;
|
||||
|
||||
|
@ -1379,14 +1581,16 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
break;
|
||||
case clc_stringcmd:
|
||||
ReadString (m, buf, sizeof(buf));
|
||||
// printf("stringcmd: %s\n", buf);
|
||||
printf("stringcmd: %s\n", buf);
|
||||
|
||||
if (!strcmp(buf, "new"))
|
||||
{
|
||||
if (qtv->parsingconnectiondata)
|
||||
if (qtv && qtv->parsingconnectiondata)
|
||||
QW_StuffcmdToViewer(v, "cmd new\n");
|
||||
else
|
||||
{
|
||||
SendServerData(qtv, v);
|
||||
}
|
||||
}
|
||||
else if (!strncmp(buf, "modellist ", 10))
|
||||
{
|
||||
|
@ -1444,6 +1648,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
SendServerData(qtv, v); //we're old.
|
||||
else
|
||||
{
|
||||
int crc;
|
||||
int r;
|
||||
char *s;
|
||||
s = buf+9;
|
||||
|
@ -1453,14 +1658,43 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
s++;
|
||||
r = atoi(s);
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
while((*s >= '0' && *s <= '9') || *s == '-')
|
||||
s++;
|
||||
while(*s == ' ')
|
||||
s++;
|
||||
crc = atoi(s);
|
||||
|
||||
if (qtv && qtv->controller == v)
|
||||
{
|
||||
if (!qtv->bsp)
|
||||
{
|
||||
QW_PrintfToViewer(v, "Proxy was unable to check your map version\n");
|
||||
qtv->drop = true;
|
||||
}
|
||||
else if (crc != BSP_Checksum(qtv->bsp))
|
||||
{
|
||||
QW_PrintfToViewer(v, "Your map (%s) does not match the servers\n", qtv->modellist[1].name);
|
||||
qtv->drop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
|
||||
if (v->server)
|
||||
if (qtv)
|
||||
{
|
||||
r = Prespawn(qtv, v->netchan.message.cursize, &msg, r);
|
||||
r = Prespawn(qtv, v->netchan.message.cursize, &msg, r, v->thisplayer);
|
||||
SendBufferToViewer(v, msg.data, msg.cursize, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = SendCurrentUserinfos(qtv, v->netchan.message.cursize, &msg, r, v->thisplayer);
|
||||
if (r > MAX_CLIENTS)
|
||||
r = -1;
|
||||
SendBufferToViewer(v, msg.data, msg.cursize, true);
|
||||
}
|
||||
else r = -1;
|
||||
|
||||
if (r < 0)
|
||||
sprintf(skin, "%ccmd spawn\n", svc_stufftext);
|
||||
|
@ -1483,7 +1717,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
else
|
||||
{
|
||||
v->thinksitsconnected = true;
|
||||
if (v->server && v->server->ispaused)
|
||||
if (qtv && qtv->ispaused)
|
||||
{
|
||||
char msgb[] = {svc_setpause, 1};
|
||||
SendBufferToViewer(v, msgb, sizeof(msgb), true);
|
||||
|
@ -1522,18 +1756,23 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
{
|
||||
}
|
||||
else if (!strncmp(buf, "say \"", 5))
|
||||
QTV_Say(cluster, qtv, v, buf+5);
|
||||
QTV_Say(cluster, qtv, v, buf+5, false);
|
||||
else if (!strncmp(buf, "say ", 4))
|
||||
QTV_Say(cluster, qtv, v, buf+4);
|
||||
QTV_Say(cluster, qtv, v, buf+4, false);
|
||||
|
||||
else if (!strncmp(buf, "say_team \"", 10))
|
||||
QTV_Say(cluster, qtv, v, buf+10, true);
|
||||
else if (!strncmp(buf, "say_team ", 9))
|
||||
QTV_Say(cluster, qtv, v, buf+9, true);
|
||||
|
||||
else if (!strncmp(buf, "servers", 7))
|
||||
{
|
||||
v->menunum = 1;
|
||||
QW_SetMenu(v, MENU_SERVERS);
|
||||
}
|
||||
else if (!strncmp(buf, "reset", 5))
|
||||
{
|
||||
QW_SetViewersServer(v, NULL);
|
||||
v->menunum = 1;
|
||||
QW_SetMenu(v, MENU_SERVERS);
|
||||
}
|
||||
else if (!strncmp(buf, "admin", 5))
|
||||
{
|
||||
|
@ -1542,14 +1781,14 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
if (Netchan_IsLocal(v->netchan.remote_address))
|
||||
{
|
||||
Sys_Printf(cluster, "Local player %s logs in as admin\n", v->name);
|
||||
v->menunum = 2;
|
||||
QW_SetMenu(v, MENU_ADMIN);
|
||||
v->isadmin = true;
|
||||
}
|
||||
else
|
||||
QW_PrintfToViewer(v, "There is no admin password set\nYou may not log in.\n");
|
||||
}
|
||||
else if (v->isadmin)
|
||||
v->menunum = 2;
|
||||
QW_SetMenu(v, MENU_ADMIN);
|
||||
else
|
||||
{
|
||||
strcpy(v->expectcommand, "admin");
|
||||
|
@ -1557,6 +1796,30 @@ 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 *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));
|
||||
Info_ValueForKey(v->userinfo, "name", v->name, sizeof(v->name));
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
SendClientCommand(v->server, "%s", buf);
|
||||
}
|
||||
|
||||
else if (!qtv)
|
||||
{
|
||||
//all the other things need an active server.
|
||||
|
@ -1604,19 +1867,27 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
}
|
||||
else
|
||||
{
|
||||
Sys_Printf(cluster, "Client sent unknown string command: %s\n", buf);
|
||||
if (v->server && v->server->controller == v)
|
||||
SendClientCommand(v->server, "%s", buf);
|
||||
else
|
||||
Sys_Printf(cluster, "Client sent unknown string command: %s\n", buf);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case clc_move:
|
||||
v->lost = ReadByte(m);
|
||||
ReadByte(m);
|
||||
ReadByte(m);
|
||||
ReadDeltaUsercmd(m, &nullcmd, &oldest);
|
||||
ReadDeltaUsercmd(m, &oldest, &oldcmd);
|
||||
ReadDeltaUsercmd(m, &oldcmd, &newcmd);
|
||||
|
||||
if (v->menunum)
|
||||
ReadDeltaUsercmd(m, &nullcmd, &v->ucmds[0]);
|
||||
ReadDeltaUsercmd(m, &v->ucmds[0], &v->ucmds[1]);
|
||||
ReadDeltaUsercmd(m, &v->ucmds[1], &v->ucmds[2]);
|
||||
/*
|
||||
if (v->server && v->server->controller)
|
||||
{
|
||||
v->
|
||||
}
|
||||
*/
|
||||
/* if (v->menunum)
|
||||
{
|
||||
if (newcmd.buttons&1 && !(oldcmd.buttons&1))
|
||||
Menu_Enter(cluster, v, 0);
|
||||
|
@ -1637,8 +1908,8 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
PMove(v, &newcmd);
|
||||
*/
|
||||
PMove(v, &v->ucmds[2]);
|
||||
break;
|
||||
case clc_tmove:
|
||||
v->origin[0] = ((signed short)ReadShort(m))/8.0f;
|
||||
|
@ -1663,25 +1934,20 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
|
||||
sv_t *sv;
|
||||
int i, min;
|
||||
char buffer[2048];
|
||||
netmsg_t m;
|
||||
InitNetMsg(&m, buffer, sizeof(buffer));
|
||||
WriteByte(&m, svc_stufftext);
|
||||
|
||||
switch(viewer->menunum)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case MENU_ADMINSERVER:
|
||||
if (viewer->server)
|
||||
{
|
||||
i = 0;
|
||||
sv = viewer->server;
|
||||
if (i++ == viewer->menuop)
|
||||
{ //mvd port
|
||||
WriteString(&m, "echo Please enter a new tcp port number\nmessagemode\n");
|
||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||
QW_StuffcmdToViewer(viewer, "echo Please enter a new tcp port number\nmessagemode\n");
|
||||
strcpy(viewer->expectcommand, "setmvdport");
|
||||
}
|
||||
if (i++ == viewer->menuop)
|
||||
|
@ -1690,17 +1956,15 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
}
|
||||
if (i++ == viewer->menuop)
|
||||
{ //back
|
||||
viewer->menunum = 2;
|
||||
viewer->menuop = 0;
|
||||
QW_SetMenu(viewer, MENU_ADMIN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//fallthrough
|
||||
case 1:
|
||||
case MENU_SERVERS:
|
||||
if (!cluster->servers)
|
||||
{
|
||||
WriteString(&m, "echo Please enter a server ip\nmessagemode\n");
|
||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||
QW_StuffcmdToViewer(viewer, "echo Please enter a server ip\nmessagemode\n");
|
||||
strcpy(viewer->expectcommand, "insecadddemo");
|
||||
}
|
||||
else
|
||||
|
@ -1719,16 +1983,14 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
{
|
||||
if (i == viewer->menuop)
|
||||
{
|
||||
if (sv->parsingconnectiondata || !sv->modellist[1].name[0])
|
||||
/*if (sv->parsingconnectiondata || !sv->modellist[1].name[0])
|
||||
{
|
||||
WriteString(&m, "echo But that stream isn't connected\n");
|
||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||
QW_PrintfToViewer(viewer, "But that stream isn't connected\n");
|
||||
}
|
||||
else
|
||||
else*/
|
||||
{
|
||||
QW_SetViewersServer(viewer, sv);
|
||||
SendBufferToViewer(viewer, m.data, m.cursize, true);
|
||||
viewer->menunum = 0;
|
||||
QW_SetMenu(viewer, MENU_NONE);
|
||||
viewer->thinksitsconnected = false;
|
||||
}
|
||||
break;
|
||||
|
@ -1736,12 +1998,11 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case MENU_ADMIN:
|
||||
i = 0;
|
||||
if (i++ == viewer->menuop)
|
||||
{ //connection stuff
|
||||
viewer->menunum = 3;
|
||||
viewer->menuop = 0;
|
||||
QW_SetMenu(viewer, MENU_ADMINSERVER);
|
||||
}
|
||||
if (i++ == viewer->menuop)
|
||||
{ //qw port
|
||||
|
@ -1791,8 +2052,7 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
}
|
||||
if (i++ == viewer->menuop)
|
||||
{ //back
|
||||
viewer->menunum = 0;
|
||||
viewer->menuop = 0;
|
||||
QW_SetMenu(viewer, MENU_NONE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2012,6 +2272,8 @@ void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
|
|||
free(viewer->backbuf[i].data);
|
||||
}
|
||||
|
||||
if (viewer->server->controller == viewer)
|
||||
viewer->server->drop = true;
|
||||
if (viewer->server)
|
||||
viewer->server->numviewers--;
|
||||
|
||||
|
@ -2029,11 +2291,12 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
|||
int qport;
|
||||
netmsg_t m;
|
||||
|
||||
sv_t *useserver;
|
||||
viewer_t *v, *f;
|
||||
|
||||
if (*cluster->master && (cluster->curtime > cluster->mastersendtime || cluster->mastersendtime > cluster->curtime + 4*1000*60)) //urm... time wrapped?
|
||||
{
|
||||
if (NET_StringToAddr(cluster->master, &from))
|
||||
if (NET_StringToAddr(cluster->master, &from, 27000))
|
||||
{
|
||||
sprintf(buffer, "a\n%i\n0\n", cluster->mastersequence++); //fill buffer with a heartbeat
|
||||
//why is there no \xff\xff\xff\xff ?..
|
||||
|
@ -2083,16 +2346,34 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
|||
{
|
||||
if (Netchan_Process(&v->netchan, &m))
|
||||
{
|
||||
useserver = v->server;
|
||||
if (useserver && useserver->parsingconnectiondata)
|
||||
useserver = NULL;
|
||||
|
||||
v->netchan.outgoing_sequence = v->netchan.incoming_sequence; //compensate for client->server packetloss.
|
||||
if (!v->server)
|
||||
v->maysend = true;
|
||||
else if (!v->chokeme || !cluster->chokeonnotupdated)
|
||||
if (v->server && v->server->controller == v)
|
||||
{
|
||||
v->maysend = true;
|
||||
v->chokeme = cluster->chokeonnotupdated;
|
||||
// v->maysend = true;
|
||||
v->server->maysend = true;
|
||||
// v->server->netchan.outgoing_sequence = v->netchan.incoming_sequence;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!v->server)
|
||||
v->maysend = true;
|
||||
else if (!v->chokeme || !cluster->chokeonnotupdated)
|
||||
{
|
||||
v->maysend = true;
|
||||
v->chokeme = cluster->chokeonnotupdated;
|
||||
}
|
||||
}
|
||||
|
||||
ParseQWC(cluster, v->server, v, &m);
|
||||
ParseQWC(cluster, useserver, v, &m);
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
{
|
||||
QTV_Run(v->server);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2120,17 +2401,26 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
|||
QW_FreeViewer(cluster, f);
|
||||
}
|
||||
|
||||
if (v->maysend && (!v->server || !v->server->parsingconnectiondata)) //don't send incompleate connection data.
|
||||
if (v->maysend) //don't send incompleate connection data.
|
||||
{
|
||||
useserver = v->server;
|
||||
if (useserver && useserver->parsingconnectiondata)
|
||||
useserver = NULL;
|
||||
|
||||
v->maysend = false;
|
||||
m.cursize = 0;
|
||||
if (v->thinksitsconnected)
|
||||
{
|
||||
SendPlayerStates(v->server, v, &m);
|
||||
UpdateStats(v->server, v);
|
||||
SendPlayerStates(useserver, v, &m);
|
||||
UpdateStats(useserver, v);
|
||||
|
||||
if (v->menunum)
|
||||
Menu_Draw(cluster, v);
|
||||
else if (v->server && v->server->parsingconnectiondata)
|
||||
{
|
||||
WriteByte(&m, svc_centerprint);
|
||||
WriteString(&m, v->server->status);
|
||||
}
|
||||
}
|
||||
Netchan_Transmit(cluster, &v->netchan, m.cursize, m.data);
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
|||
strncpy(cluster->master, arg[1], sizeof(cluster->master)-1);
|
||||
cluster->mastersendtime = cluster->curtime;
|
||||
|
||||
if (NET_StringToAddr(arg[1], &addr)) //send a ping like a qw server does. this is kinda pointless of course.
|
||||
if (NET_StringToAddr(arg[1], &addr, 27000)) //send a ping like a qw server does. this is kinda pointless of course.
|
||||
NET_SendPacket (cluster, cluster->qwdsocket, 1, "k", addr);
|
||||
|
||||
return "Master server set.\n";
|
||||
|
@ -346,7 +346,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
|||
memmove(arg[1]+4, arg[1], ARG_LEN-5);
|
||||
strncpy(arg[1], "tcp:", 4);
|
||||
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, !strcmp(arg[0], "connect")))
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, !strcmp(arg[0], "connect"), false))
|
||||
return "Failed to connect to server, connection aborted\n";
|
||||
return "Connection registered\n";
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
|||
memmove(arg[1]+4, arg[1], ARG_LEN-5);
|
||||
strncpy(arg[1], "udp:", 4);
|
||||
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, false))
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, false, false))
|
||||
return "Failed to connect to server, connection aborted\n";
|
||||
return "Connection registered\n";
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
|||
memmove(arg[1]+5, arg[1], ARG_LEN-6);
|
||||
strncpy(arg[1], "file:", 5);
|
||||
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, false))
|
||||
if (!QTV_NewServerConnection(cluster, arg[1], false, false, false))
|
||||
return "Failed to connect to server, connection aborted\n";
|
||||
return "Connection registered\n";
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ char *Cluster_Rcon_Dispatch(cluster_t *cluster, char *arg[MAX_ARGS], char *buffe
|
|||
else if (!strcmp(arg[0], "ping"))
|
||||
{
|
||||
netadr_t addr;
|
||||
if (NET_StringToAddr(arg[1], &addr))
|
||||
if (NET_StringToAddr(arg[1], &addr, 27500))
|
||||
{
|
||||
NET_SendPacket (cluster, cluster->qwdsocket, 1, "k", addr);
|
||||
return "pinged\n";
|
||||
|
|
240
fteqtv/source.c
240
fteqtv/source.c
|
@ -30,8 +30,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define UDPTIMEOUT_LENGTH (1000*20)
|
||||
#define UDPPACKETINTERVAL (1000/72)
|
||||
|
||||
void Net_SendConnectionMVD(sv_t *qtv, oproxy_t *prox);
|
||||
|
||||
qboolean NET_StringToAddr (char *s, netadr_t *sadr)
|
||||
|
||||
qboolean NET_StringToAddr (char *s, netadr_t *sadr, int defaultport)
|
||||
{
|
||||
struct hostent *h;
|
||||
char *colon;
|
||||
|
@ -129,7 +131,7 @@ dblbreak:
|
|||
{
|
||||
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
|
||||
|
||||
((struct sockaddr_in *)sadr)->sin_port = 0;
|
||||
((struct sockaddr_in *)sadr)->sin_port = htons(defaultport);
|
||||
|
||||
strcpy (copy, s);
|
||||
// strip off a trailing :port if present
|
||||
|
@ -215,7 +217,7 @@ qboolean Net_ConnectToTCPServer(sv_t *qtv, char *ip)
|
|||
netadr_t from;
|
||||
unsigned long nonblocking = true;
|
||||
|
||||
if (!NET_StringToAddr(ip+4, &qtv->serveraddress))
|
||||
if (!NET_StringToAddr(ip+4, &qtv->serveraddress, 27500))
|
||||
{
|
||||
Sys_Printf(qtv->cluster, "Unable to resolve %s\n", ip);
|
||||
return false;
|
||||
|
@ -242,11 +244,7 @@ qboolean Net_ConnectToTCPServer(sv_t *qtv, char *ip)
|
|||
|
||||
if (connect(qtv->sourcesock, (struct sockaddr *)&qtv->serveraddress, sizeof(qtv->serveraddress)) == INVALID_SOCKET)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (qerrno != WSAEINPROGRESS)
|
||||
#else
|
||||
if (qerrno != EINPROGRESS)
|
||||
#endif
|
||||
{
|
||||
closesocket(qtv->sourcesock);
|
||||
qtv->sourcesock = INVALID_SOCKET;
|
||||
|
@ -260,7 +258,7 @@ qboolean Net_ConnectToUDPServer(sv_t *qtv, char *ip)
|
|||
netadr_t from;
|
||||
unsigned long nonblocking = true;
|
||||
|
||||
if (!NET_StringToAddr(ip+4, &qtv->serveraddress))
|
||||
if (!NET_StringToAddr(ip+4, &qtv->serveraddress, 27500))
|
||||
{
|
||||
Sys_Printf(qtv->cluster, "Unable to resolve %s\n", ip);
|
||||
return false;
|
||||
|
@ -349,7 +347,6 @@ void Net_FindProxies(sv_t *qtv)
|
|||
return;
|
||||
}
|
||||
memset(prox, 0, sizeof(*prox));
|
||||
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
||||
prox->sock = sock;
|
||||
prox->file = NULL;
|
||||
|
||||
|
@ -357,6 +354,8 @@ void Net_FindProxies(sv_t *qtv)
|
|||
qtv->proxies = prox;
|
||||
|
||||
qtv->numproxies++;
|
||||
|
||||
Net_SendConnectionMVD(qtv, prox);
|
||||
}
|
||||
|
||||
qboolean Net_FileProxy(sv_t *qtv, char *filename)
|
||||
|
@ -374,7 +373,7 @@ qboolean Net_FileProxy(sv_t *qtv, char *filename)
|
|||
if (!prox)
|
||||
return false;
|
||||
memset(prox, 0, sizeof(*prox));
|
||||
prox->flushing = true; //allow the buffer overflow resumption code to send the connection info.
|
||||
|
||||
prox->sock = INVALID_SOCKET;
|
||||
prox->file = f;
|
||||
|
||||
|
@ -383,6 +382,8 @@ qboolean Net_FileProxy(sv_t *qtv, char *filename)
|
|||
|
||||
qtv->numproxies++;
|
||||
|
||||
Net_SendConnectionMVD(qtv, prox);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -435,7 +436,9 @@ void Net_TryFlushProxyBuffer(cluster_t *cluster, oproxy_t *prox)
|
|||
char *buffer;
|
||||
int length;
|
||||
int bufpos;
|
||||
fd_set wfds;
|
||||
|
||||
if (prox->drop)
|
||||
return;
|
||||
|
||||
while (prox->bufferpos >= MAX_PROXY_BUFFER)
|
||||
{ //so we never get any issues with wrapping..
|
||||
|
@ -602,7 +605,7 @@ void Net_SendConnectionMVD(sv_t *qtv, oproxy_t *prox)
|
|||
|
||||
for(prespawn = 0;prespawn>=0;)
|
||||
{
|
||||
prespawn = Prespawn(qtv, 0, &msg, prespawn);
|
||||
prespawn = Prespawn(qtv, 0, &msg, prespawn, MAX_CLIENTS-1);
|
||||
|
||||
Prox_SendMessage(qtv->cluster, prox, msg.data, msg.cursize, dem_read, (unsigned)-1);
|
||||
msg.cursize = 0;
|
||||
|
@ -923,7 +926,8 @@ qboolean QTV_Connect(sv_t *qtv, char *serverurl)
|
|||
else
|
||||
{
|
||||
qtv->parsetime = Sys_Milliseconds() + BUFFERTIME*1000;
|
||||
Sys_Printf(qtv->cluster, "Buffering for %i seconds\n", BUFFERTIME);
|
||||
if (!qtv->usequkeworldprotocols)
|
||||
Sys_Printf(qtv->cluster, "Buffering for %i seconds\n", BUFFERTIME);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1296,6 +1300,123 @@ void SendClientCommand(sv_t *qtv, char *fmt, ...)
|
|||
WriteString(&qtv->netchan.message, buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChooseFavoriteTrack(sv_t *tv)
|
||||
{
|
||||
int frags, best, pnum;
|
||||
char buffer[64];
|
||||
|
||||
frags = -10000;
|
||||
best = -1;
|
||||
if (tv->controller)
|
||||
best = tv->trackplayer;
|
||||
else
|
||||
{
|
||||
for (pnum = 0; pnum < MAX_CLIENTS; pnum++)
|
||||
{
|
||||
if (*tv->players[pnum].userinfo && !atoi(Info_ValueForKey(tv->players[pnum].userinfo, "*spectator", buffer, sizeof(buffer))))
|
||||
{
|
||||
if (tv->thisplayer == pnum)
|
||||
continue;
|
||||
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 const unsigned char chktbl[1024] = {
|
||||
0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
|
||||
0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
|
||||
0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58,
|
||||
0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3,
|
||||
0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b,
|
||||
0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36,
|
||||
0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8,
|
||||
0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27,
|
||||
0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd,
|
||||
0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63,
|
||||
0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2,
|
||||
0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d,
|
||||
0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65,
|
||||
0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f,
|
||||
0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f,
|
||||
0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42,
|
||||
0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59,
|
||||
0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9,
|
||||
0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69,
|
||||
0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba,
|
||||
0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85,
|
||||
0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4,
|
||||
0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8,
|
||||
0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa,
|
||||
0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05,
|
||||
0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7,
|
||||
0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a,
|
||||
0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb,
|
||||
0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b,
|
||||
0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d,
|
||||
0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce,
|
||||
0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3
|
||||
};
|
||||
|
||||
|
||||
unsigned char COM_BlockSequenceCRCByte (unsigned char *base, int length, int sequence)
|
||||
{
|
||||
unsigned short crc;
|
||||
const unsigned char *p;
|
||||
unsigned char chkb[60 + 4];
|
||||
|
||||
p = chktbl + (sequence % (sizeof(chktbl) - 4));
|
||||
|
||||
if (length > 60)
|
||||
length = 60;
|
||||
memcpy (chkb, base, length);
|
||||
|
||||
chkb[length] = (sequence & 0xff) ^ p[0];
|
||||
chkb[length+1] = p[1];
|
||||
chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2];
|
||||
chkb[length+3] = p[3];
|
||||
|
||||
length += 4;
|
||||
|
||||
crc = QCRC_Block(chkb, length);
|
||||
|
||||
crc &= 0xff;
|
||||
|
||||
return crc;
|
||||
}
|
||||
void SetMoveCRC(sv_t *qtv, netmsg_t *msg)
|
||||
{
|
||||
char *outbyte;
|
||||
outbyte = msg->data + msg->startpos+1;
|
||||
|
||||
*outbyte = COM_BlockSequenceCRCByte(
|
||||
outbyte+1, msg->cursize - (msg->startpos+2),
|
||||
qtv->netchan.outgoing_sequence);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void QTV_ParseQWStream(sv_t *qtv)
|
||||
{
|
||||
char buffer[1500];
|
||||
|
@ -1318,18 +1439,25 @@ void QTV_ParseQWStream(sv_t *qtv)
|
|||
{
|
||||
if (buffer[4] == 'c')
|
||||
{ //got a challenge
|
||||
strcpy(qtv->status, "Attemping connection\n");
|
||||
qtv->challenge = atoi(buffer+5);
|
||||
sprintf(buffer, "connect %i %i %i \"%s\"", 28, qtv->qport, qtv->challenge, "\\*ver\\fteqtv\\name\\fteqtv\\spectator\\1\\rate\\10000");
|
||||
if (qtv->controller)
|
||||
sprintf(buffer, "connect %i %i %i \"%s\"", 28, qtv->qport, qtv->challenge, qtv->controller->userinfo);
|
||||
else
|
||||
sprintf(buffer, "connect %i %i %i \"%s\\name\\%s\"", 28, qtv->qport, qtv->challenge, "\\*ver\\fteqtv\\spectator\\1\\rate\\10000", qtv->cluster->hostname);
|
||||
Netchan_OutOfBand(qtv->cluster, qtv->sourcesock, qtv->serveraddress, strlen(buffer), buffer);
|
||||
continue;
|
||||
}
|
||||
if (buffer[4] == 'n')
|
||||
{
|
||||
strncpy(qtv->status, buffer+5, sizeof(qtv->status));
|
||||
qtv->status[sizeof(qtv->status)-1] = 0;
|
||||
Sys_Printf(qtv->cluster, "%s: %s", qtv->server, buffer+5);
|
||||
continue;
|
||||
}
|
||||
if (buffer[4] == 'j')
|
||||
{
|
||||
strcpy(qtv->status, "Waiting for gamestate\n");
|
||||
Netchan_Setup(qtv->sourcesock, &qtv->netchan, qtv->serveraddress, qtv->qport, true);
|
||||
|
||||
qtv->trackplayer = -1;
|
||||
|
@ -1358,10 +1486,16 @@ void QTV_ParseQWStream(sv_t *qtv)
|
|||
|
||||
if (qtv->simtime < qtv->oldpackettime)
|
||||
qtv->simtime = qtv->oldpackettime; //too old
|
||||
|
||||
if (qtv->controller)
|
||||
{
|
||||
qtv->controller->maysend = true;
|
||||
qtv->controller->netchan.outgoing_sequence = qtv->netchan.incoming_sequence;
|
||||
qtv->controller->netchan.incoming_sequence = qtv->netchan.incoming_acknowledged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QTV_Run(sv_t *qtv)
|
||||
{
|
||||
int lengthofs;
|
||||
|
@ -1370,7 +1504,7 @@ void QTV_Run(sv_t *qtv)
|
|||
int oldcurtime;
|
||||
int packettime;
|
||||
|
||||
if (qtv->disconnectwhennooneiswatching && qtv->numviewers == 0)
|
||||
if (qtv->drop || (qtv->disconnectwhennooneiswatching && qtv->numviewers == 0))
|
||||
{
|
||||
QTV_Shutdown(qtv);
|
||||
return;
|
||||
|
@ -1410,6 +1544,7 @@ void QTV_Run(sv_t *qtv)
|
|||
|
||||
if (!qtv->isconnected && (qtv->curtime >= qtv->nextconnectattempt || qtv->curtime < qtv->nextconnectattempt - UDPRECONNECT_TIME*2))
|
||||
{
|
||||
strcpy(qtv->status, "Attemping challenge\n");
|
||||
Netchan_OutOfBand(qtv->cluster, qtv->sourcesock, qtv->serveraddress, 13, "getchallenge\n");
|
||||
qtv->nextconnectattempt = qtv->curtime + UDPRECONNECT_TIME;
|
||||
}
|
||||
|
@ -1417,7 +1552,7 @@ void QTV_Run(sv_t *qtv)
|
|||
|
||||
if (qtv->isconnected)
|
||||
{
|
||||
char buffer[64];
|
||||
char buffer[128];
|
||||
netmsg_t msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.data = buffer;
|
||||
|
@ -1430,8 +1565,23 @@ void QTV_Run(sv_t *qtv)
|
|||
return;
|
||||
}
|
||||
|
||||
if (qtv->curtime < qtv->packetratelimiter - UDPPACKETINTERVAL*2)
|
||||
qtv->packetratelimiter = qtv->curtime;
|
||||
if (qtv->controller)
|
||||
{
|
||||
qtv->netchan.outgoing_sequence = qtv->controller->netchan.incoming_sequence;
|
||||
qtv->netchan.incoming_sequence = qtv->controller->netchan.incoming_acknowledged;
|
||||
if (qtv->maysend)
|
||||
{
|
||||
qtv->maysend = false;
|
||||
qtv->curtime = qtv->packetratelimiter;
|
||||
}
|
||||
else
|
||||
qtv->curtime = qtv->packetratelimiter - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (qtv->curtime < qtv->packetratelimiter - UDPPACKETINTERVAL*2)
|
||||
qtv->packetratelimiter = qtv->curtime;
|
||||
}
|
||||
if (qtv->curtime >= qtv->packetratelimiter)
|
||||
{
|
||||
qtv->packetratelimiter += UDPPACKETINTERVAL;
|
||||
|
@ -1440,11 +1590,38 @@ void QTV_Run(sv_t *qtv)
|
|||
{
|
||||
qtv->nextsendpings = qtv->curtime + PINGSINTERVAL_TIME;
|
||||
SendClientCommand(qtv, "pings\n");
|
||||
|
||||
}
|
||||
ChooseFavoriteTrack(qtv);
|
||||
|
||||
if (qtv->trackplayer >= 0)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
else if (qtv->controller)
|
||||
{
|
||||
WriteByte(&msg, clc_tmove);
|
||||
WriteShort(&msg, qtv->controller->origin[0]);
|
||||
WriteShort(&msg, qtv->controller->origin[1]);
|
||||
WriteShort(&msg, qtv->controller->origin[2]);
|
||||
|
||||
/* qtv->controller->ucmds[0].angles[1] = qtv->curtime*120;
|
||||
qtv->controller->ucmds[1].angles[1] = qtv->curtime*120;
|
||||
qtv->controller->ucmds[2].angles[1] = qtv->curtime*120;
|
||||
*/
|
||||
msg.startpos = msg.cursize;
|
||||
WriteByte(&msg, clc_move);
|
||||
WriteByte(&msg, 0);
|
||||
WriteByte(&msg, 0);
|
||||
WriteDeltaUsercmd(&msg, &nullcmd, &qtv->controller->ucmds[0]);
|
||||
WriteDeltaUsercmd(&msg, &qtv->controller->ucmds[0], &qtv->controller->ucmds[1]);
|
||||
WriteDeltaUsercmd(&msg, &qtv->controller->ucmds[1], &qtv->controller->ucmds[2]);
|
||||
|
||||
SetMoveCRC(qtv, &msg);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -1719,9 +1896,20 @@ void Cluster_Run(cluster_t *cluster)
|
|||
QW_UpdateUDPStuff(cluster);
|
||||
}
|
||||
|
||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose)
|
||||
sv_t *QTV_NewServerConnection(cluster_t *cluster, char *server, qboolean force, qboolean autoclose, qboolean noduplicates)
|
||||
{
|
||||
sv_t *qtv = malloc(sizeof(sv_t));
|
||||
sv_t *qtv;
|
||||
|
||||
if (noduplicates)
|
||||
{
|
||||
for (qtv = cluster->servers; qtv; qtv = qtv->next)
|
||||
{
|
||||
if (!strcmp(qtv->server, server))
|
||||
return qtv;
|
||||
}
|
||||
}
|
||||
|
||||
qtv = malloc(sizeof(sv_t));
|
||||
if (!qtv)
|
||||
return NULL;
|
||||
|
||||
|
@ -1787,8 +1975,10 @@ int main(int argc, char **argv)
|
|||
cluster_t cluster;
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef SIGPIPE
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue