From cb3f383214ddfbe118730a8ccd06dce77ebc604a Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 20 Feb 2006 01:33:13 +0000 Subject: [PATCH] Lateset set of changes make it more easily configurable. Connect to it as localhost and use the admin alias. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1976 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- fteqtv/netchan.c | 10 ++ fteqtv/parse.c | 22 ++- fteqtv/qtv.h | 10 +- fteqtv/qtvprox.dsp | 1 + fteqtv/qw.c | 344 +++++++++++++++++++++++++++++++++++++++++++-- fteqtv/rcon.c | 7 + fteqtv/source.c | 57 ++++++++ 7 files changed, 432 insertions(+), 19 deletions(-) diff --git a/fteqtv/netchan.c b/fteqtv/netchan.c index a7e283dd8..136bd945c 100644 --- a/fteqtv/netchan.c +++ b/fteqtv/netchan.c @@ -35,7 +35,17 @@ void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, net } } +int Netchan_IsLocal (netadr_t adr) +{ + struct sockaddr_in *sadr = (struct sockaddr_in *)adr; + if (sadr->sin_addr.S_un.S_un_b.s_b1 == 127 && + sadr->sin_addr.S_un.S_un_b.s_b2 == 0 && + sadr->sin_addr.S_un.S_un_b.s_b3 == 0 && + sadr->sin_addr.S_un.S_un_b.s_b4 == 1) + return true; + return false; +} diff --git a/fteqtv/parse.c b/fteqtv/parse.c index e074ea4a7..11dc5cbeb 100644 --- a/fteqtv/parse.c +++ b/fteqtv/parse.c @@ -939,6 +939,22 @@ void ParseLightstyle(sv_t *tv, netmsg_t *m) Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, dem_read, (unsigned)-1); } +void ParseNails2(sv_t *tv, netmsg_t *m) +{ + int count; + int nailnum; + int i; + unsigned char bits[6]; + count = (unsigned char)ReadByte(m); + while(count-- > 0) + { + nailnum = ReadByte(m); + for (i = 0; i < 6; i++) + bits[i] = ReadByte(m); + } +//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) { netmsg_t buf; @@ -1139,9 +1155,9 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask) case svc_updatepl: ParsePacketloss(tv, &buf, to, mask); break; - -//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 - + case svc_nails2: + ParseNails2(tv, &buf); + break; default: buf.readpos = buf.startpos; Sys_Printf(tv->cluster, "Can't handle svc %i\n", (unsigned int)ReadByte(&buf)); diff --git a/fteqtv/qtv.h b/fteqtv/qtv.h index 1f1b299bd..54fecb9bc 100644 --- a/fteqtv/qtv.h +++ b/fteqtv/qtv.h @@ -259,6 +259,9 @@ typedef struct viewer_s { float origin[3]; + int isadmin; + char expectcommand[16]; + sv_t *server; int menunum; @@ -500,8 +503,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen); #define svc_setinfo 51 // setinfo on a client #define svc_serverinfo 52 // serverinfo #define svc_updatepl 53 // [qbyte] [qbyte] - -//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 +#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 @@ -587,12 +589,16 @@ void QW_UpdateUDPStuff(cluster_t *qtv); 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); void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean reliable); +void QW_PrintfToViewer(viewer_t *v, char *format, ...); +void QW_StuffcmdToViewer(viewer_t *v, char *format, ...); void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport); void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...); +int Netchan_IsLocal (netadr_t adr); void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, char *data, netadr_t adr); qboolean Net_CompareAddress(netadr_t *s1, netadr_t *s2, int qp1, int qp2); qboolean Netchan_Process (netchan_t *chan, netmsg_t *msg); diff --git a/fteqtv/qtvprox.dsp b/fteqtv/qtvprox.dsp index 0938968aa..0471f76a6 100644 --- a/fteqtv/qtvprox.dsp +++ b/fteqtv/qtvprox.dsp @@ -39,6 +39,7 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c diff --git a/fteqtv/qw.c b/fteqtv/qw.c index a5dc30b03..6999ca804 100644 --- a/fteqtv/qw.c +++ b/fteqtv/qw.c @@ -261,6 +261,10 @@ int SendCurrentUserinfos(sv_t *tv, int cursize, netmsg_t *msg, int 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++) { @@ -272,12 +276,19 @@ int SendCurrentUserinfos(sv_t *tv, int cursize, netmsg_t *msg, int i) WriteByte(msg, i); WriteLong(msg, i); WriteString(msg, tv->players[i].userinfo); - } - WriteByte(msg, svc_updateuserinfo); - WriteByte(msg, MAX_CLIENTS-1); - WriteLong(msg, MAX_CLIENTS-1); - WriteString(msg, "\\*spectator\\1\\name\\YOU!"); + WriteByte(msg, svc_updatefrags); + WriteByte(msg, i); + WriteShort(msg, tv->players[i].frags); + + WriteByte(msg, svc_updateping); + WriteByte(msg, i); + WriteShort(msg, tv->players[i].ping); + + WriteByte(msg, svc_updatepl); + WriteByte(msg, i); + WriteByte(msg, tv->players[i].packetloss); + } i++; @@ -464,6 +475,10 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage) Info_ValueForKey(infostring, "name", viewer->name, sizeof(viewer->name)); Netchan_OutOfBandPrint(cluster, cluster->qwdsocket, *addr, "j"); + + QW_PrintfToViewer(viewer, "Welcome to FTEQTV\n"); + QW_StuffcmdToViewer(viewer, "alias admin \"cmd admin\"\n"); + QW_PrintfToViewer(viewer, "Type admin for the admin menu\n"); } void QTV_Rcon(cluster_t *cluster, char *message, netadr_t *from) @@ -1037,7 +1052,7 @@ void PMove(viewer_t *v, usercmd_t *cmd) 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, viewer_t *v, char *message) +void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message) { char buf[1024]; netmsg_t msg; @@ -1045,6 +1060,72 @@ void QTV_Say(cluster_t *cluster, viewer_t *v, char *message) if (message[strlen(message)-1] == '\"') message[strlen(message)-1] = '\0'; + if (*v->expectcommand && v->menunum) + { + buf[sizeof(buf)-1] = '\0'; + if (!strcmp(v->expectcommand, "hostname")) + { + strncpy(cluster->hostname, message, sizeof(cluster->hostname)); + cluster->hostname[sizeof(cluster->hostname)-1] = '\0'; + } + else if (!strcmp(v->expectcommand, "master")) + { + strncpy(cluster->master, message, sizeof(cluster->master)); + cluster->master[sizeof(cluster->master)-1] = '\0'; + if (!strcmp(cluster->master, ".")) + *cluster->master = '\0'; + cluster->mastersendtime = cluster->curtime; + } + else if (!strcmp(v->expectcommand, "addserver")) + { + _snprintf(buf, sizeof(buf), "tcp:%s", message); + qtv = QTV_NewServerConnection(cluster, buf, false); + if (qtv) + { + v->server = qtv; + QW_StuffcmdToViewer(v, "cmd new\n"); + QW_PrintfToViewer(v, "Connected\n", message); + } + else + QW_PrintfToViewer(v, "Failed to connect to server \"%s\", connection aborted\n", message); + } + else if (!strcmp(v->expectcommand, "admin")) + { + if (!strcmp(message, cluster->password)) + { + v->menunum = 2; + v->isadmin = true; + Sys_Printf(cluster, "Player %s logs in as admin\n", v->name); + } + else + { + QW_PrintfToViewer(v, "Admin password incorrect\n"); + Sys_Printf(cluster, "Player %s gets incorrect admin password\n", v->name); + } + } + else if (!strcmp(v->expectcommand, "adddemo")) + { + _snprintf(buf, sizeof(buf), "file:%s", message); + qtv = QTV_NewServerConnection(cluster, buf, false); + if (!qtv) + QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message); + else + { + v->server = qtv; + QW_StuffcmdToViewer(v, "cmd new\n"); + QW_PrintfToViewer(v, "Opened demo file.\n", message); + } + } + else + { + QW_PrintfToViewer(v, "Command %s was not recognised\n", v->expectcommand); + } + + *v->expectcommand = '\0'; + return; + } + *v->expectcommand = '\0'; + InitNetMsg(&msg, buf, sizeof(buf)); WriteByte(&msg, svc_print); @@ -1089,6 +1170,28 @@ void QW_PrintfToViewer(viewer_t *v, char *format, ...) SendBufferToViewer(v, buf, strlen(buf)+1, true); } + +void QW_StuffcmdToViewer(viewer_t *v, char *format, ...) +{ + va_list argptr; + char buf[1024]; + netmsg_t msg; + InitNetMsg(&msg, buf, sizeof(buf)); + + va_start (argptr, format); +#ifdef _WIN32 + _vsnprintf (buf+1, sizeof(buf) - 2, format, argptr); + buf[sizeof(buf) - 2] = '\0'; +#else + vsnprintf (buf+1, sizeof(buf)-1, format, argptr); +#endif // _WIN32 + va_end (argptr); + + buf[0] = svc_stufftext; + + SendBufferToViewer(v, buf, strlen(buf)+1, true); +} + static const filename_t ConnectionlessModelList[] = {{""}, {"maps/start.bsp"}, {"progs/player.mdl"}, {""}}; static const filename_t ConnectionlessSoundList[] = {{""}, {""}}; @@ -1245,19 +1348,41 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m) { } else if (!strncmp(buf, "say \"", 5) && !cluster->notalking) - QTV_Say(cluster, v, buf+5); + QTV_Say(cluster, qtv, v, buf+5); else if (!strncmp(buf, "say ", 4) && !cluster->notalking) - QTV_Say(cluster, v, buf+4); + QTV_Say(cluster, qtv, v, buf+4); else if (!strncmp(buf, "servers", 7)) { v->menunum = 1; } - else if (!strncmp(buf, "reset", 7)) + else if (!strncmp(buf, "reset", 5)) { + QW_StuffcmdToViewer(v, "cmd new\n"); v->server = NULL; v->menunum = 1; } + else if (!strncmp(buf, "admin", 5)) + { + if (!*cluster->password) + { + if (Netchan_IsLocal(v->netchan.remote_address)) + { + Sys_Printf(cluster, "Local player %s logs in as admin\n", v->name); + v->menunum = 2; + 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; + else + { + strcpy(v->expectcommand, "admin"); + QW_StuffcmdToViewer(v, "echo Please enter the rcon password\nmessagemode\n"); + } + } else if (!qtv) { @@ -1375,6 +1500,27 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum) default: break; + case 3: + if (viewer->server) + { + i = 0; + if (i++ == viewer->menuop) + { //mvd port + QW_StuffcmdToViewer(viewer, "echo You will need to reconnect\n"); + cluster->qwlistenportnum += buttonnum?-1:1; + } + if (i++ == viewer->menuop) + { //disconnect + QTV_Shutdown(viewer->server); + } + if (i++ == viewer->menuop) + { //back + viewer->menunum = 2; + viewer->menuop = 0; + } + break; + } + //fallthrough case 1: if (!cluster->servers) { @@ -1415,6 +1561,67 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum) } } } + break; + case 2: + i = 0; + if (i++ == viewer->menuop) + { //connection stuff + viewer->menunum = 3; + viewer->menuop = 0; + } + if (i++ == viewer->menuop) + { //qw port + QW_StuffcmdToViewer(viewer, "echo You will need to reconnect\n"); + cluster->qwlistenportnum += buttonnum?-1:1; + } + if (i++ == viewer->menuop) + { //hostname + strcpy(viewer->expectcommand, "hostname"); + QW_StuffcmdToViewer(viewer, "echo Please enter the new hostname\nmessagemode\n"); + } + if (i++ == viewer->menuop) + { //master + strcpy(viewer->expectcommand, "master"); + QW_StuffcmdToViewer(viewer, "echo Please enter the master dns or ip\necho Enter '.' for masterless mode\nmessagemode\n"); + } + if (i++ == viewer->menuop) + { //password + strcpy(viewer->expectcommand, "password"); + QW_StuffcmdToViewer(viewer, "echo Please enter the new rcon password\nmessagemode\n"); + } + if (i++ == viewer->menuop) + { //add server + strcpy(viewer->expectcommand, "messagemode"); + QW_StuffcmdToViewer(viewer, "echo Please enter the new qtv server dns or ip\naddserver\n"); + } + if (i++ == viewer->menuop) + { //add demo + strcpy(viewer->expectcommand, "adddemo"); + QW_StuffcmdToViewer(viewer, "echo Please enter the name of the demo to play\nmessagemode\n"); + } + if (i++ == viewer->menuop) + { //choke + cluster->chokeonnotupdated ^= 1; + } + if (i++ == viewer->menuop) + { //late forwarding + cluster->lateforward ^= 1; + } + if (i++ == viewer->menuop) + { //no talking + cluster->notalking ^= 1; + } + if (i++ == viewer->menuop) + { //nobsp + cluster->nobsp ^= 1; + } + if (i++ == viewer->menuop) + { //back + viewer->menunum = 0; + viewer->menuop = 0; + } + + break; } } @@ -1435,7 +1642,6 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer) WriteString2(&m, "FTEQTV\n"); if (strcmp(cluster->hostname, DEFAULT_HOSTNAME)) WriteString2(&m, cluster->hostname); - WriteString2(&m, "\n\n"); switch(viewer->menunum) { @@ -1443,8 +1649,48 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer) WriteString2(&m, "bad menu"); break; + case 3: //per-connection options + if (viewer->server) + { + sv = viewer->server; + WriteString2(&m, "\n\nConnection Admin\n"); + WriteString2(&m, sv->hostname); + if (sv->file) + WriteString2(&m, " (demo)"); + WriteString2(&m, "\n\n"); + + if (viewer->menuop < 0) + viewer->menuop = 0; + + i = 0; + WriteString2(&m, " port"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20i", sv->tcplistenportnum); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " disconnect"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " back"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + if (viewer->menuop >= i) + viewer->menuop = i - 1; + + break; + } + //fallthrough case 1: //connections list + WriteString2(&m, "\n\nServers\n\n"); + if (!cluster->servers) { WriteString2(&m, "No active connections"); @@ -1480,17 +1726,87 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer) break; case 2: //admin menu - WriteString2(&m, " port"); - WriteString2(&m, (viewer->menuop==0)?" \r ":" : "); + + WriteString2(&m, "\n\nCluster Admin\n\n"); + + if (viewer->menuop < 0) + viewer->menuop = 0; + i = 0; + + WriteString2(&m, " this connection"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " port"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); sprintf(str, "%-20i", cluster->qwlistenportnum); WriteString2(&m, str); WriteString2(&m, "\n"); - WriteString2(&m, "hostname"); - WriteString2(&m, (viewer->menuop==1)?" \r ":" : "); + WriteString2(&m, " hostname"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); sprintf(str, "%-20s", cluster->hostname); WriteString2(&m, str); WriteString2(&m, "\n"); + + WriteString2(&m, " master"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", cluster->master); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " password"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " add server"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " add demo"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " choke"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", cluster->chokeonnotupdated?"yes":"no"); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, "delay forwarding"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", cluster->lateforward?"yes":"no"); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " talking"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", cluster->notalking?"no":"yes"); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " nobsp"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", cluster->nobsp?"yes":"no"); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + WriteString2(&m, " back"); + WriteString2(&m, (viewer->menuop==(i++))?" \r ":" : "); + sprintf(str, "%-20s", "..."); + WriteString2(&m, str); + WriteString2(&m, "\n"); + + if (viewer->menuop >= i) + viewer->menuop = i - 1; break; } diff --git a/fteqtv/rcon.c b/fteqtv/rcon.c index 1adb1c774..652327f08 100644 --- a/fteqtv/rcon.c +++ b/fteqtv/rcon.c @@ -554,6 +554,13 @@ char *Server_Rcon_Dispatch(sv_t *qtv, char *arg[MAX_ARGS], char *buffer, int siz else return "Failed (will keep trying)\n"; } + + else if (!strcmp(arg[0], "disconnect")) + { + QTV_Shutdown(qtv); + return NULL; + } + else if (!strcmp(arg[0], "file") || !strcmp(arg[0], "play") || !strcmp(arg[0], "playdemo")) { if (!*arg[1]) diff --git a/fteqtv/source.c b/fteqtv/source.c index 1295c5b9f..8657487ef 100644 --- a/fteqtv/source.c +++ b/fteqtv/source.c @@ -862,6 +862,63 @@ qboolean QTV_Connect(sv_t *qtv, char *serverurl) } return true; } + +void QTV_Shutdown(sv_t *qtv) +{ + return; +/* + viewer_t *v; + sv_t *peer; + cluster_t *cluster; + Sys_Printf(qtv->cluster, "Shutting down %s\n", qtv->server); + + if (qtv->sourcesock != INVALID_SOCKET) + { + int err; + err = qerrno; + if (qerrno) + Sys_Printf(qtv->cluster, "Error: source socket error %i\n", qerrno); + else + Sys_Printf(qtv->cluster, "Error: server disconnected\n"); + closesocket(qtv->sourcesock); + qtv->sourcesock = INVALID_SOCKET; + } + if (qtv->file) + { + fclose(qtv->file); + qtv->file = NULL; + } + BSP_Free(qtv->bsp); + qtv->bsp = NULL; + + cluster = qtv->cluster; + if (cluster->servers == qtv) + cluster->servers = qtv->next; + else + { + for (peer = cluster->servers; peer->next; peer = peer->next) + { + if (peer->next == qtv) + { + peer->next = qtv->next; + break; + } + } + } + + for (v = cluster->viewers; v; v = v->next) + { + if (v->server == qtv) + { + v->server = NULL; + v->menunum = 1; + } + } + + free(qtv); +*/ +} + /* void QTV_Run(sv_t *qtv) {