cameras start at intermission spots, stream change messages for other users, cleaned up the menu code a little

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2458 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-01-06 09:46:32 +00:00
parent 5596b146fe
commit 47f9440a30
6 changed files with 466 additions and 67 deletions

View file

@ -36,8 +36,15 @@ struct bsp_s {
unsigned char decpvs[(MAX_MAP_LEAFS+7)/8]; //decompressed pvs
int pvsbytecount;
int numintermissionspots;
intermission_t intermissionspot[8];
};
static const intermission_t intermissionspot;
typedef struct
{
@ -113,10 +120,152 @@ void DecompressVis(unsigned char *in, unsigned char *out, int bytecount)
}
}
void BSP_LoadEntities(bsp_t *bsp, char *entitydata)
{
char *v;
char key[2048];
char value[2048];
enum {et_random, et_startspot, et_primarystart, et_intermission} etype;
float org[3];
float angles[3];
qboolean foundstartspot = false;
float startspotorg[3];
float startspotangles[3];
//char *COM_ParseToken (char *data, char *out, int outsize, const char *punctuation)
while (entitydata)
{
entitydata = COM_ParseToken(entitydata, key, sizeof(key), NULL);
if (!entitydata)
break;
if (!strcmp(key, "{"))
{
org[0] = 0;
org[1] = 0;
org[2] = 0;
angles[0] = 0;
angles[1] = 0;
angles[2] = 0;
etype = et_random;
for(;;)
{
if(!entitydata)
{
printf("unexpected eof in bsp entities section\n");
return;
}
entitydata = COM_ParseToken(entitydata, key, sizeof(key), NULL);
if (!strcmp(key, "}"))
break;
entitydata = COM_ParseToken(entitydata, value, sizeof(value), NULL);
if (!strcmp(key, "origin"))
{
v = value;
v = COM_ParseToken(v, key, sizeof(key), NULL);
org[0] = atof(key);
v = COM_ParseToken(v, key, sizeof(key), NULL);
org[1] = atof(key);
v = COM_ParseToken(v, key, sizeof(key), NULL);
org[2] = atof(key);
}
if (!strcmp(key, "angles") || !strcmp(key, "angle") || !strcmp(key, "mangle"))
{
v = value;
v = COM_ParseToken(v, key, sizeof(key), NULL);
angles[0] = atof(key);
v = COM_ParseToken(v, key, sizeof(key), NULL);
if (v)
{
angles[1] = atof(key);
v = COM_ParseToken(v, key, sizeof(key), NULL);
angles[2] = atof(key);
}
else
{
angles[1] = angles[0];
angles[0] = 0;
angles[2] = 0;
}
}
if (!strcmp(key, "classname"))
{
if (!strcmp(value, "info_player_start"))
etype = et_primarystart;
if (!strcmp(value, "info_deathmatch_start"))
etype = et_startspot;
if (!strcmp(value, "info_intermission"))
etype = et_intermission;
}
}
switch (etype)
{
case et_primarystart: //a single player start
memcpy(startspotorg, org, sizeof(startspotorg));
memcpy(startspotangles, angles, sizeof(startspotangles));
foundstartspot = true;
break;
case et_startspot:
if (!foundstartspot)
{
memcpy(startspotorg, org, sizeof(startspotorg));
memcpy(startspotangles, angles, sizeof(startspotangles));
foundstartspot = true;
}
break;
case et_intermission:
if (bsp->numintermissionspots < sizeof(bsp->intermissionspot)/sizeof(bsp->intermissionspot[0]))
{
bsp->intermissionspot[bsp->numintermissionspots].pos[0] = org[0];
bsp->intermissionspot[bsp->numintermissionspots].pos[1] = org[1];
bsp->intermissionspot[bsp->numintermissionspots].pos[2] = org[2];
bsp->intermissionspot[bsp->numintermissionspots].angle[0] = angles[0];
bsp->intermissionspot[bsp->numintermissionspots].angle[1] = angles[1];
bsp->intermissionspot[bsp->numintermissionspots].angle[2] = angles[2];
bsp->numintermissionspots++;
}
break;
}
}
else
{
printf("data not expected here\n");
return;
}
}
if (foundstartspot && !bsp->numintermissionspots)
{
bsp->intermissionspot[bsp->numintermissionspots].pos[0] = startspotorg[0];
bsp->intermissionspot[bsp->numintermissionspots].pos[1] = startspotorg[1];
bsp->intermissionspot[bsp->numintermissionspots].pos[2] = startspotorg[2];
bsp->intermissionspot[bsp->numintermissionspots].angle[0] = startspotangles[0];
bsp->intermissionspot[bsp->numintermissionspots].angle[1] = startspotangles[1];
bsp->intermissionspot[bsp->numintermissionspots].angle[2] = startspotangles[2];
bsp->numintermissionspots++;
}
}
bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
{
unsigned char *data;
unsigned int size;
char *entdata;
dheader_t *header;
dplane_t *planes;
@ -159,10 +308,13 @@ bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
nodes = (dnode_t*)(data+LittleLong(header->lumps[LUMP_NODES].fileofs));
leaf = (dleaf_t*)(data+LittleLong(header->lumps[LUMP_LEAFS].fileofs));
entdata = (char*)(data+LittleLong(header->lumps[LUMP_ENTITIES].fileofs));
numnodes = LittleLong(header->lumps[LUMP_NODES].filelen)/sizeof(dnode_t);
numleafs = LittleLong(header->lumps[LUMP_LEAFS].filelen)/sizeof(dleaf_t);
bsp = malloc(sizeof(bsp_t) + sizeof(node_t)*numnodes + LittleLong(header->lumps[LUMP_VISIBILITY].filelen) + sizeof(unsigned char *)*numleafs);
bsp->numintermissionspots = 0;
if (bsp)
{
bsp->fullchecksum = 0;
@ -204,6 +356,8 @@ bsp_t *BSP_LoadModel(cluster_t *cluster, char *gamedir, char *bspname)
}
}
BSP_LoadEntities(bsp, entdata);
free(data);
return bsp;
@ -318,3 +472,16 @@ void BSP_SetupForPosition(bsp_t *bsp, float x, float y, float z)
DecompressVis(bsp->pvsofs[leafnum], bsp->decpvs, bsp->pvsbytecount);
}
const intermission_t *BSP_IntermissionSpot(bsp_t *bsp)
{
int spotnum;
if (bsp)
{
if (bsp->numintermissionspots>0)
{
spotnum = rand()%bsp->numintermissionspots;
return &bsp->intermissionspot[spotnum];
}
}
return &intermissionspot;
}

View file

@ -1688,7 +1688,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 || !tv->usequkeworldprotocols)
if (tv->cluster->nobsp)// || !tv->usequkeworldprotocols)
tv->bsp = NULL;
else
tv->bsp = BSP_LoadModel(tv->cluster, tv->gamedir, tv->modellist[1].name);

View file

@ -496,6 +496,11 @@ typedef struct {
char bits[6];
} nail_t;
typedef struct {
float pos[3];
float angle[3];
} intermission_t;
struct sv_s {
char connectpassword[64]; //password given to server
netadr_t serveraddress;
@ -879,7 +884,9 @@ unsigned int BSP_Checksum(bsp_t *bsp);
int BSP_SphereLeafNums(bsp_t *bsp, int maxleafs, unsigned short *list, float x, float y, float z, float radius);
qboolean BSP_Visible(bsp_t *bsp, int leafcount, unsigned short *list);
void BSP_SetupForPosition(bsp_t *bsp, float x, float y, float z);
void QW_SetViewersServer(viewer_t *viewer, sv_t *sv);
const intermission_t *BSP_IntermissionSpot(bsp_t *bsp);
void QW_SetViewersServer(cluster_t *cluster, viewer_t *viewer, sv_t *sv);
unsigned short QCRC_Block (unsigned char *start, int count);
unsigned short QCRC_Value(unsigned short crcvalue);
void WriteDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move);

View file

@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static const filename_t ConnectionlessModelList[] = {{""}, {"maps/start.bsp"}, {"progs/player.mdl"}, {""}};
static const filename_t ConnectionlessSoundList[] = {{""}, {""}};
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean noupwards);
void QTV_DefaultMovevars(movevars_t *vars)
{
vars->gravity = 800;
@ -620,8 +622,26 @@ int SendList(sv_t *qtv, int first, const filename_t *list, int svc, netmsg_t *ms
return i;
}
void QW_SetViewersServer(viewer_t *viewer, sv_t *sv)
void QW_StreamPrint(cluster_t *cluster, sv_t *server, viewer_t *allbut, char *message)
{
viewer_t *v;
for (v = cluster->viewers; v; v = v->next)
{
if (v->server == server)
{
if (v == allbut)
continue;
QW_PrintfToViewer(v, "%s", message);
}
}
}
void QW_SetViewersServer(cluster_t *cluster, viewer_t *viewer, sv_t *sv)
{
char buffer[1024];
sv_t *oldserver;
oldserver = viewer->server;
if (viewer->server)
viewer->server->numviewers--;
viewer->server = sv;
@ -635,6 +655,17 @@ void QW_SetViewersServer(viewer_t *viewer, sv_t *sv)
viewer->origin[0] = 0;
viewer->origin[1] = 0;
viewer->origin[2] = 0;
if (sv != oldserver)
{
if (sv)
{
snprintf(buffer, sizeof(buffer), "%cQTV%c%s leaves to watch %s (%i)\n", 91+128, 93+128, viewer->name, *sv->hostname?sv->hostname:sv->server, sv->streamid);
QW_StreamPrint(cluster, oldserver, viewer, buffer);
}
snprintf(buffer, sizeof(buffer), "%cQTV%c%s joins the stream\n", 91+128, 93+128, viewer->name);
QW_StreamPrint(cluster, sv, viewer, buffer);
}
}
//fixme: will these want to have state?..
@ -655,16 +686,8 @@ void NewClient(cluster_t *cluster, viewer_t *viewer)
viewer->timeout = cluster->curtime + 15*1000;
viewer->trackplayer = -1;
if (!viewer->server)
{
QW_SetMenu(viewer, MENU_SERVERS);
}
else
{
viewer->menunum = -1;
QW_SetMenu(viewer, MENU_NONE);
}
QW_PrintfToViewer(viewer, "Welcome to FTEQTV build %i\n", cluster->buildnumber);
@ -682,11 +705,22 @@ void NewClient(cluster_t *cluster, viewer_t *viewer)
QW_StuffcmdToViewer(viewer, "alias \"proxy:menu\" \"say proxy:menu\"\n");
QW_StuffcmdToViewer(viewer, "alias \"proxy:backspace\" \"say proxy:menu backspace\"\n");
QW_StuffcmdToViewer(viewer, "alias \".help\" \"say .help\"\n");
QW_StuffcmdToViewer(viewer, "alias \".disconnect\" \"say .disconnect\"\n");
QW_StuffcmdToViewer(viewer, "alias \".menu\" \"say .menu\"\n");
QW_StuffcmdToViewer(viewer, "alias \".admin\" \"say .admin\"\n");
QW_StuffcmdToViewer(viewer, "alias \".reset\" \"say .reset\"\n");
QW_StuffcmdToViewer(viewer, "alias \".clients\" \"say .clients\"\n");
// QW_StuffcmdToViewer(viewer, "alias \".qtv\" \"say .qtv\"\n");
// QW_StuffcmdToViewer(viewer, "alias \".join\" \"say .join\"\n");
// QW_StuffcmdToViewer(viewer, "alias \".observe\" \"say .observe\"\n");
QW_PrintfToViewer(viewer, "Type admin for the admin menu\n");
}
void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
{
char buf[1024];
float rate;
char temp[64];
Info_ValueForKey(viewer->userinfo, "name", temp, sizeof(temp));
@ -695,6 +729,27 @@ void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
strcpy(temp, "unnamed");
if (!*viewer->name)
Sys_Printf(cluster, "Viewer %s connected\n", temp);
if (strcmp(viewer->name, temp))
{
if (*viewer->name)
{
snprintf(buf, sizeof(buf), "%cQTV%c%s changed name to %cQTV%c%s\n",
91+128, 93+128, viewer->name,
91+128, 93+128, temp
);
}
else
{
snprintf(buf, sizeof(buf), "%cQTV%c%s joins the stream\n",
91+128, 93+128, temp
);
}
QW_StreamPrint(cluster, viewer->server, NULL, buf);
}
Q_strncpyz(viewer->name, temp, sizeof(viewer->name));
Info_ValueForKey(viewer->userinfo, "rate", temp, sizeof(temp));
@ -855,6 +910,8 @@ void QW_SetMenu(viewer_t *v, int menunum)
{
if (menunum != MENU_NONE)
{
QW_StuffcmdToViewer(v, "//set prox_inmenu 1\n");
QW_StuffcmdToViewer(v, "alias \"+proxfwd\" \"proxy:up\"\n");
QW_StuffcmdToViewer(v, "alias \"+proxback\" \"proxy:down\"\n");
QW_StuffcmdToViewer(v, "alias \"+proxleft\" \"proxy:left\"\n");
@ -867,6 +924,8 @@ void QW_SetMenu(viewer_t *v, int menunum)
}
else
{
QW_StuffcmdToViewer(v, "//set prox_inmenu 0\n");
QW_StuffcmdToViewer(v, "alias \"+proxfwd\" \"+forward\"\n");
QW_StuffcmdToViewer(v, "alias \"+proxback\" \"+back\"\n");
QW_StuffcmdToViewer(v, "alias \"+proxleft\" \"+moveleft\"\n");
@ -1419,7 +1478,6 @@ void SendNQClientData(sv_t *tv, viewer_t *v, netmsg_t *msg)
void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg)
{
int miss;
int e;
int i;
usercmd_t to;
@ -2139,7 +2197,7 @@ void PMove(viewer_t *v, usercmd_t *cmd)
v->velocity[2] = pmove.velocity[2];
}
void QW_SetCommentator(viewer_t *v, viewer_t *commentator)
void QW_SetCommentator(cluster_t *cluster, viewer_t *v, viewer_t *commentator)
{
// if (v->commentator == commentator)
// return;
@ -2154,7 +2212,7 @@ void QW_SetCommentator(viewer_t *v, viewer_t *commentator)
QW_PrintfToViewer(v, "Following commentator %s\n", commentator->name);
if (v->server != commentator->server)
QW_SetViewersServer(v, commentator->server);
QW_SetViewersServer(cluster, v, commentator->server);
}
else
{
@ -2195,7 +2253,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
qtv = QTV_NewServerConnection(cluster, buf, "", false, false, false);
if (qtv)
{
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected\n", message);
}
else
@ -2215,6 +2273,19 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
Sys_Printf(cluster, "Player %s gets incorrect admin password\n", v->name);
}
}
else if (!strcmp(v->expectcommand, "insecadddemo"))
{
snprintf(buf, sizeof(buf), "file:%s", message);
qtv = QTV_NewServerConnection(cluster, buf, "", false, false, false);
if (!qtv)
QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message);
else
{
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Opened demo file.\n", message);
}
}
else if (!strcmp(v->expectcommand, "adddemo"))
{
snprintf(buf, sizeof(buf), "file:%s", message);
@ -2223,7 +2294,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
QW_PrintfToViewer(v, "Failed to play demo \"%s\"\n", message);
else
{
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Opened demo file.\n", message);
}
}
@ -2277,11 +2348,41 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
".bind\n"
);
}
else if (!strncmp(message, ".menu", 5))
{
message += 5;
if (v->conmenussupported)
goto guimenu;
else
goto tuimenu;
}
else if (!strncmp(message, ".tuimenu", 8))
{
message += 8;
tuimenu:
if (v->menunum)
QW_SetMenu(v, MENU_NONE);
else
QW_SetMenu(v, MENU_SERVERS);
}
else if (!strncmp(message, ".guimenu", 8))
{
sv_t *sv;
int y;
qboolean shownheader = false;
qboolean shownheader;
message += 8;
guimenu:
QW_SetMenu(v, MENU_NONE);
shownheader = false;
QW_StuffcmdToViewer(v,
"alias menucallback\n"
@ -2402,14 +2503,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
}
else if (!strncmp(message, ".reset", 6))
{
QW_SetViewersServer(v, NULL);
QW_SetMenu(v, MENU_SERVERS);
}
else if (!strncmp(message, ".menu", 5))
{
if (v->menunum)
QW_SetMenu(v, MENU_NONE);
else
QW_SetViewersServer(cluster, v, NULL);
QW_SetMenu(v, MENU_SERVERS);
}
else if (!strncmp(message, ".admin", 6))
@ -2444,7 +2538,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (qtv)
{
QW_SetMenu(v, MENU_NONE);
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected\n", message);
}
else
@ -2458,7 +2552,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (qtv)
{
QW_SetMenu(v, MENU_NONE);
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
qtv->controller = v;
QW_PrintfToViewer(v, "Connected\n", message);
}
@ -2473,7 +2567,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (qtv)
{
QW_SetMenu(v, MENU_NONE);
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected\n", message);
}
else
@ -2494,7 +2588,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (qtv)
{
QW_SetMenu(v, MENU_NONE);
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected\n", message);
}
else
@ -2510,7 +2604,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (qtv)
{
QW_SetMenu(v, MENU_NONE);
QW_SetViewersServer(v, qtv);
QW_SetViewersServer(cluster, v, qtv);
QW_PrintfToViewer(v, "Connected\n", message);
}
else
@ -2519,7 +2613,7 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
else if (!strncmp(message, ".disconnect", 11))
{
QW_SetMenu(v, MENU_SERVERS);
QW_SetViewersServer(v, NULL);
QW_SetViewersServer(cluster, v, NULL);
QW_PrintfToViewer(v, "Connected\n", message);
}
else if (!strncmp(message, "admin", 11))
@ -2544,12 +2638,12 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (ov->server)
{
if (ov->server->controller == ov)
QW_PrintfToViewer(v, "%s: %s\n", ov->name, ov->server->server);
QW_PrintfToViewer(v, "%i: %s: %s\n", ov->userid, ov->name, ov->server->server);
else
QW_PrintfToViewer(v, "%s: %s\n", ov->name, ov->server->server);
QW_PrintfToViewer(v, "%i: %s: %s\n", ov->userid, ov->name, ov->server->server);
}
else
QW_PrintfToViewer(v, "%s: %s\n", ov->name, "None");
QW_PrintfToViewer(v, "%i: %s: %s\n", ov->userid, ov->name, "None");
}
else
remaining++;
@ -2557,21 +2651,21 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (remaining)
QW_PrintfToViewer(v, "%i clients not shown\n", remaining);
}
else if (!strncmp(message, ".followid ", 8))
else if (!strncmp(message, ".followid ", 10))
{
int id = atoi(message+8);
int id = atoi(message+10);
viewer_t *cv;
for (cv = cluster->viewers; cv; cv = cv->next)
{
if (cv->userid == id)
{
QW_SetCommentator(v, cv);
QW_SetCommentator(cluster, v, cv);
return;
}
}
QW_PrintfToViewer(v, "Couldn't find that player\n");
QW_SetCommentator(v, NULL);
QW_SetCommentator(cluster, v, NULL);
}
else if (!strncmp(message, ".follow ", 8))
{
@ -2582,16 +2676,16 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
{
if (!strcmp(cv->name, id))
{
QW_SetCommentator(v, cv);
QW_SetCommentator(cluster, v, cv);
return;
}
}
QW_PrintfToViewer(v, "Couldn't find that player\n");
QW_SetCommentator(v, NULL);
QW_SetCommentator(cluster, v, NULL);
}
else if (!strncmp(message, ".follow", 7))
{
QW_SetCommentator(v, NULL);
QW_SetCommentator(cluster, v, NULL);
}
else if (!strncmp(message, "proxy:menu up", 13))
{
@ -2659,6 +2753,52 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
QW_PrintfToViewer(v, "All keys bound not recognised\n");
}
else if (!strncmp(message, ".bsay ", 6))
{
viewer_t *ov;
if (cluster->notalking)
return;
message += 6;
for (ov = cluster->viewers; ov; ov = ov->next)
{
InitNetMsg(&msg, buf, sizeof(buf));
WriteByte(&msg, svc_print);
if (ov->netchan.isnqprotocol)
WriteByte(&msg, 1);
else
{
if (ov->conmenussupported)
{
WriteByte(&msg, 3); //PRINT_CHAT
WriteString2(&msg, "[^sBQTV^s]^s^5");
}
else
{
WriteByte(&msg, 2); //PRINT_HIGH
WriteByte(&msg, 91+128);
WriteString2(&msg, "BQTV");
WriteByte(&msg, 93+128);
WriteByte(&msg, 0);
WriteByte(&msg, svc_print);
WriteByte(&msg, 3); //PRINT_CHAT
}
}
WriteString2(&msg, v->name);
WriteString2(&msg, ": ");
// WriteString2(&msg, "\x8d ");
WriteString2(&msg, message);
WriteString(&msg, "\n");
SendBufferToViewer(ov, msg.data, msg.cursize, true);
}
}
else if (!strncmp(message, ".", 1) && strncmp(message, "..", 2))
{
QW_PrintfToViewer(v, "Proxy command not recognised\n");
@ -2709,16 +2849,25 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
if (ov->conmenussupported)
{
WriteByte(&msg, 3); //PRINT_CHAT
WriteString2(&msg, "^s^5");
WriteString2(&msg, "[^sQTV^s]^s^5");
}
else
{
WriteByte(&msg, 2); //PRINT_HIGH
WriteByte(&msg, 91+128);
WriteString2(&msg, "QTV");
WriteByte(&msg, 93+128);
WriteByte(&msg, 0);
WriteByte(&msg, svc_print);
WriteByte(&msg, 3); //PRINT_CHAT
}
}
WriteString2(&msg, v->name);
WriteString2(&msg, "\x8d ");
WriteString2(&msg, ": ");
// WriteString2(&msg, "\x8d ");
WriteString2(&msg, message);
WriteString(&msg, "\n");
@ -2767,6 +2916,37 @@ void QW_StuffcmdToViewer(viewer_t *v, char *format, ...)
SendBufferToViewer(v, buf, strlen(buf)+1, true);
}
void QW_PositionAtIntermission(sv_t *qtv, viewer_t *v)
{
netmsg_t msg;
char buf[4];
const intermission_t *spot;
if (qtv)
spot = BSP_IntermissionSpot(qtv->bsp);
else
spot = BSP_IntermissionSpot(NULL);
v->origin[0] = spot->pos[0];
v->origin[1] = spot->pos[1];
v->origin[2] = spot->pos[2];
msg.data = buf;
msg.maxsize = sizeof(buf);
msg.cursize = 0;
msg.overflowed = 0;
WriteByte (&msg, svc_setangle);
WriteByte (&msg, (spot->angle[0]/360) * 256);
WriteByte (&msg, (spot->angle[1]/360) * 256);
WriteByte (&msg, 0);//spot->angle[2]);
SendBufferToViewer(v, msg.data, msg.cursize, true);
}
void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
{
char buf[MAX_NQMSGLEN];
@ -2861,11 +3041,21 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
SendNQSpawnInfoToViewer(cluster, v, &msg);
SendBufferToViewer(v, msg.data, msg.cursize, true);
QW_PositionAtIntermission(qtv, v);
v->thinksitsconnected = true;
}
else if (!strncmp(buf, "begin", 5))
{
int oldmenu;
v->thinksitsconnected = true;
oldmenu = v->menunum;
QW_SetMenu(v, MENU_NONE);
QW_SetMenu(v, oldmenu);
if (!v->server)
QTV_Say(cluster, v->server, v, ".menu", false);
}
else if (!strncmp(buf, "say \"", 5))
@ -2930,12 +3120,14 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
// usercmd_t oldest, oldcmd, newcmd;
char buf[1024];
netmsg_t msg;
int i;
v->delta_frame = -1;
while (m->readpos < m->cursize)
{
switch (ReadByte(m))
i = ReadByte(m);
switch (i)
{
case clc_nop:
return;
@ -3075,9 +3267,12 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
char skin[64];
sprintf(skin, "%cskins\n", svc_stufftext);
SendBufferToViewer(v, skin, strlen(skin)+1, true);
QW_PositionAtIntermission(qtv, v);
}
else if (!strncmp(buf, "begin", 5))
{
int oldmenu;
viewer_t *com;
if (atoi(buf+6) != v->servercount)
SendServerData(qtv, v); //this is unfortunate!
@ -3089,11 +3284,20 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
char msgb[] = {svc_setpause, 1};
SendBufferToViewer(v, msgb, sizeof(msgb), true);
}
}
oldmenu = v->menunum;
QW_SetMenu(v, MENU_NONE);
QW_SetMenu(v, oldmenu);
com = v->commentator;
v->commentator = NULL;
QW_SetCommentator(v, com);
QW_SetCommentator(cluster, v, com);
if (!v->server)
QTV_Say(cluster, v->server, v, ".menu", false);
}
}
else if (!strncmp(buf, "download", 8))
{
@ -3132,7 +3336,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
else if (!strncmp(buf, "ptrack", 6))
{
v->trackplayer = -1;
QW_SetCommentator(v, NULL);
QW_SetCommentator(cluster, v, NULL);
}
else if (!strncmp(buf, "pings", 5))
{
@ -3259,6 +3463,7 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
return;
default:
Sys_Printf(cluster, "bad clc from %s\n", v->name);
v->drop = true;
return;
}
@ -3326,7 +3531,7 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
}
else*/
{
QW_SetViewersServer(viewer, sv);
QW_SetViewersServer(cluster, viewer, sv);
QW_SetMenu(viewer, MENU_NONE);
viewer->thinksitsconnected = false;
}
@ -3406,6 +3611,10 @@ void Menu_Draw(cluster_t *cluster, viewer_t *viewer)
unsigned char *s;
netmsg_t m;
if (viewer->backbuffered)
return;
InitNetMsg(&m, buffer, sizeof(buffer));
WriteByte(&m, svc_centerprint);
@ -3594,11 +3803,15 @@ static const char dropcmd[] = {svc_stufftext, 'd', 'i', 's', 'c', 'o', 'n', 'n',
void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
{
char buf[1024];
viewer_t *oview;
int i;
//note: unlink them yourself.
// Sys_Printf(cluster, "Dropping viewer %s\n", viewer->name);
snprintf(buf, sizeof(buf), "%cQTV%c%s leaves the proxy\n", 91+128, 93+128, viewer->name);
QW_StreamPrint(cluster, viewer->server, NULL, buf);
Sys_Printf(cluster, "Dropping viewer %s\n", viewer->name);
//spam them thrice, then forget about them
Netchan_Transmit(cluster, &viewer->netchan, strlen(dropcmd)+1, dropcmd);
@ -3622,7 +3835,7 @@ void QW_FreeViewer(cluster_t *cluster, viewer_t *viewer)
for (oview = cluster->viewers; oview; oview = oview->next)
{
if (oview->commentator == viewer)
QW_SetCommentator(oview, NULL);
QW_SetCommentator(cluster, oview, NULL);
}
free(viewer);
@ -3803,6 +4016,7 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
{
if (Net_CompareAddress(&v->netchan.remote_address, &from, 0, 0))
{
Sys_Printf(cluster, "Dup connect from %s\n", v->name);
v->drop = true;
}
}

View file

@ -527,6 +527,14 @@ char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffe
catbuffer(buffer, sizeofbuffer, " Talking allowed\n");
if (cluster->nobsp)
catbuffer(buffer, sizeofbuffer, " No BSP loading\n");
if (cluster->tcpsocket != INVALID_SOCKET)
{
catbuffer(buffer, sizeofbuffer, " tcp port %i\n", cluster->tcplistenportnum);
}
if (cluster->tcpsocket != INVALID_SOCKET)
{
catbuffer(buffer, sizeofbuffer, " udp port %i\n", cluster->qwlistenportnum);
}
catbuffer(buffer, sizeofbuffer, "\n");
@ -557,6 +565,9 @@ char *Cmd_Status(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buffe
if (*qtv->connectpassword)
catbuffer(buffer, sizeofbuffer, "Using a password\n");
if (qtv->disconnectwhennooneiswatching)
catbuffer(buffer, sizeofbuffer, "Stream is temporary\n");
if (qtv->tcpsocket != INVALID_SOCKET)
{
catbuffer(buffer, sizeofbuffer, "Listening for proxies (%i)\n", qtv->tcplistenportnum);
@ -762,11 +773,11 @@ char *Cmd_MVDPort(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buff
if (!newp)
{
if (qtv->tcpsocket != INVALID_SOCKET)
if (cluster->tcpsocket != INVALID_SOCKET)
{
closesocket(qtv->tcpsocket);
qtv->tcpsocket = INVALID_SOCKET;
qtv->tcplistenportnum = 0;
closesocket(cluster->tcpsocket);
cluster->tcpsocket = INVALID_SOCKET;
cluster->tcplistenportnum = 0;
return "mvd port is now closed\n";
}
@ -778,11 +789,10 @@ char *Cmd_MVDPort(cluster_t *cluster, sv_t *qtv, char *arg[MAX_ARGS], char *buff
if (news != INVALID_SOCKET)
{
if (qtv->tcpsocket != INVALID_SOCKET)
closesocket(qtv->tcpsocket);
qtv->tcpsocket = news;
qtv->disconnectwhennooneiswatching = false;
qtv->tcplistenportnum = newp;
if (cluster->tcpsocket != INVALID_SOCKET)
closesocket(cluster->tcpsocket);
cluster->tcpsocket = news;
cluster->tcplistenportnum = newp;
return "Opened tcp port\n";
}
else
@ -859,8 +869,8 @@ const rconcommands_t rconcommands[] =
{"disconnect", 1, 0, Cmd_Disconnect},
{"record", 1, 0, Cmd_Record},
{"stop", 1, 0, Cmd_Stop},
{"tcpport", 1, 0, Cmd_MVDPort},
{"mvdport", 1, 0, Cmd_MVDPort},
{"tcpport", 0, 1, Cmd_MVDPort},
{"mvdport", 0, 1, Cmd_MVDPort},
#ifdef VIEWER
{"watch", 1, 0, Cmd_Watch},

View file

@ -864,8 +864,9 @@ void QTV_Shutdown(sv_t *qtv)
{
if (v->server == qtv)
{
QW_SetViewersServer(v, NULL);
QW_SetMenu(v, MENU_SERVERS);
QW_SetViewersServer(qtv->cluster, v, NULL);
QW_SetMenu(v, MENU_NONE);
QTV_Say(cluster, v->server, v, ".menu", false);
QW_PrintfToViewer(v, "Stream %s is closing\n", qtv->server);
}
}