Added predictable spectator movement. Changed chat to only show to clients on that stream. Added rate limiting. Fixed the stats bug. Added a .clients command.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2421 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
51ba51cb03
commit
af5348a8f2
5 changed files with 411 additions and 92 deletions
|
@ -4,7 +4,7 @@ STRIP=strip
|
|||
|
||||
STRIPFLAGS=--strip-unneeded --remove-section=.comment
|
||||
|
||||
OBJS = netchan.o parse.o qw.o source.o bsp.o rcon.o mdfour.o crc.o control.o forward.o
|
||||
OBJS = netchan.o parse.o qw.o source.o bsp.o rcon.o mdfour.o crc.o control.o forward.o pmove.o
|
||||
|
||||
qtv: $(OBJS) qtv.h
|
||||
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@.db -lm
|
||||
|
|
161
fteqtv/pmove.c
Normal file
161
fteqtv/pmove.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
#include "qtv.h"
|
||||
#include <math.h>
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
void AngleVectors (vec3_t angles, float *forward, float *right, float *up)
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[1] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[0] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[2] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = cp*sy;
|
||||
forward[2] = -sp;
|
||||
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
||||
right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
||||
right[2] = -1*sr*cp;
|
||||
up[0] = (cr*sp*cy+-sr*-sy);
|
||||
up[1] = (cr*sp*sy+-sr*cy);
|
||||
up[2] = cr*cp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define DotProduct(a,b) ((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2]))
|
||||
#define VectorCopy(a,b) do{b[0]=a[0];b[1]=a[1];b[2]=a[2];}while(0)
|
||||
#define VectorClear(v) do{v[0]=0;v[1]=0;v[2]=0;}while(0)
|
||||
#define VectorScale(i,s,o) do{o[0]=i[0]*s;o[1]=i[1]*s;o[2]=i[2]*s;}while(0)
|
||||
#define Length(v) sqrt(DotProduct(v, v))
|
||||
#define VectorMA(base,s,m,out) do{out[0]=base[0]+s*m[0];out[1]=base[1]+s*m[1];out[2]=base[2]+s*m[2];}while(0)
|
||||
#define SHORT2ANGLE(s) ((s*360.0f)/65536)
|
||||
|
||||
float VectorNormalize(vec3_t v)
|
||||
{
|
||||
float len, ilen;
|
||||
len = Length(v);
|
||||
if (len)
|
||||
{
|
||||
ilen = 1/len;
|
||||
v[0] *= ilen;
|
||||
v[1] *= ilen;
|
||||
v[2] *= ilen;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void PM_SpectatorMove (pmove_t *pmove)
|
||||
{
|
||||
float speed, drop, friction, control, newspeed;
|
||||
float currentspeed, addspeed, accelspeed;
|
||||
int i;
|
||||
vec3_t wishvel;
|
||||
float fmove, smove;
|
||||
vec3_t wishdir;
|
||||
float wishspeed;
|
||||
|
||||
// friction
|
||||
|
||||
speed = Length (pmove->velocity);
|
||||
if (speed < 1)
|
||||
{
|
||||
VectorClear (pmove->velocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
drop = 0;
|
||||
|
||||
friction = pmove->movevars.friction*1.5; // extra friction
|
||||
control = speed < pmove->movevars.stopspeed ? pmove->movevars.stopspeed : speed;
|
||||
drop += control*friction*pmove->frametime;
|
||||
|
||||
// scale the velocity
|
||||
newspeed = speed - drop;
|
||||
if (newspeed < 0)
|
||||
newspeed = 0;
|
||||
newspeed /= speed;
|
||||
|
||||
VectorScale (pmove->velocity, newspeed, pmove->velocity);
|
||||
}
|
||||
|
||||
// accelerate
|
||||
fmove = pmove->cmd.forwardmove;
|
||||
smove = pmove->cmd.sidemove;
|
||||
|
||||
VectorNormalize (pmove->forward);
|
||||
VectorNormalize (pmove->right);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
wishvel[i] = pmove->forward[i]*fmove + pmove->right[i]*smove;
|
||||
wishvel[2] += pmove->cmd.upmove;
|
||||
|
||||
VectorCopy (wishvel, wishdir);
|
||||
wishspeed = VectorNormalize(wishdir);
|
||||
|
||||
//
|
||||
// clamp to server defined max speed
|
||||
//
|
||||
if (wishspeed > pmove->movevars.spectatormaxspeed)
|
||||
{
|
||||
VectorScale (wishvel, pmove->movevars.spectatormaxspeed/wishspeed, wishvel);
|
||||
wishspeed = pmove->movevars.spectatormaxspeed;
|
||||
}
|
||||
|
||||
currentspeed = DotProduct(pmove->velocity, wishdir);
|
||||
addspeed = wishspeed - currentspeed;
|
||||
|
||||
// Buggy QW spectator mode, kept for compatibility
|
||||
// if (pmove->pm_type == PM_OLD_SPECTATOR)
|
||||
{
|
||||
if (addspeed <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (addspeed > 0)
|
||||
{
|
||||
accelspeed = pmove->movevars.accelerate*pmove->frametime*wishspeed;
|
||||
if (accelspeed > addspeed)
|
||||
accelspeed = addspeed;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
pmove->velocity[i] += accelspeed*wishdir[i];
|
||||
}
|
||||
|
||||
// move
|
||||
VectorMA (pmove->origin, pmove->frametime, pmove->velocity, pmove->origin);
|
||||
}
|
||||
|
||||
void PM_PlayerMove (pmove_t *pmove)
|
||||
{
|
||||
pmove->frametime = pmove->cmd.msec * 0.001;
|
||||
/*
|
||||
if (pmove.pm_type == PM_NONE || pmove.pm_type == PM_FREEZE)
|
||||
{
|
||||
PM_CategorizePosition ();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// take angles directly from command
|
||||
pmove->angles[0] = SHORT2ANGLE(pmove->cmd.angles[0]);
|
||||
pmove->angles[1] = SHORT2ANGLE(pmove->cmd.angles[1]);
|
||||
pmove->angles[2] = SHORT2ANGLE(pmove->cmd.angles[2]);
|
||||
|
||||
AngleVectors (pmove->angles, pmove->forward, pmove->right, pmove->up);
|
||||
|
||||
// if (pmove->pm_type == PM_SPECTATOR || pmove->pm_type == PM_OLD_SPECTATOR)
|
||||
{
|
||||
PM_SpectatorMove (pmove);
|
||||
// pmove->onground = false;
|
||||
return;
|
||||
}
|
||||
}
|
50
fteqtv/qtv.h
50
fteqtv/qtv.h
|
@ -356,6 +356,36 @@ typedef struct {
|
|||
} usercmd_t;
|
||||
extern const usercmd_t nullcmd;
|
||||
|
||||
|
||||
typedef float vec3_t[3];
|
||||
typedef struct {
|
||||
float gravity;
|
||||
float maxspeed;
|
||||
float spectatormaxspeed;
|
||||
float accelerate;
|
||||
float airaccelerate;
|
||||
float waterfriction;
|
||||
float entgrav;
|
||||
float stopspeed;
|
||||
float wateraccelerate;
|
||||
float friction;
|
||||
} movevars_t;
|
||||
typedef struct {
|
||||
//in / out
|
||||
vec3_t origin;
|
||||
vec3_t velocity;
|
||||
|
||||
//in
|
||||
usercmd_t cmd;
|
||||
movevars_t movevars;
|
||||
|
||||
//internal
|
||||
vec3_t angles;
|
||||
float frametime;
|
||||
vec3_t forward, right, up;
|
||||
} pmove_t;
|
||||
|
||||
|
||||
#define MAX_BACK_BUFFERS 16
|
||||
typedef struct sv_s sv_t;
|
||||
typedef struct cluster_s cluster_t;
|
||||
|
@ -384,7 +414,7 @@ typedef struct viewer_s {
|
|||
struct viewer_s *next;
|
||||
|
||||
char name[32];
|
||||
char userinfo[256];
|
||||
char userinfo[1024];
|
||||
|
||||
int lost; //packets
|
||||
usercmd_t ucmds[3];
|
||||
|
@ -392,7 +422,8 @@ typedef struct viewer_s {
|
|||
|
||||
int settime; //the time that we last told the client.
|
||||
|
||||
float origin[3];
|
||||
vec3_t velocity;
|
||||
vec3_t origin;
|
||||
|
||||
int isadmin;
|
||||
char expectcommand[16];
|
||||
|
@ -474,18 +505,7 @@ struct sv_s {
|
|||
|
||||
char gamedir[MAX_QPATH];
|
||||
char mapname[256];
|
||||
struct {
|
||||
float gravity;
|
||||
float maxspeed;
|
||||
float spectatormaxspeed;
|
||||
float accelerate;
|
||||
float airaccelerate;
|
||||
float waterfriction;
|
||||
float entgrav;
|
||||
float stopspeed;
|
||||
float wateraccelerate;
|
||||
float friction;
|
||||
} movevars;
|
||||
movevars_t movevars;
|
||||
int cdtrack;
|
||||
entity_t entity[MAX_ENTITIES];
|
||||
frame_t frame[MAX_ENTITY_FRAMES];
|
||||
|
@ -825,6 +845,8 @@ void SendBufferToViewer(viewer_t *v, const char *buffer, int length, qboolean re
|
|||
void QW_PrintfToViewer(viewer_t *v, char *format, ...);
|
||||
void QW_StuffcmdToViewer(viewer_t *v, char *format, ...);
|
||||
|
||||
void PM_PlayerMove (pmove_t *pmove);
|
||||
|
||||
void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qboolean isclient);
|
||||
void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...);
|
||||
int Netchan_IsLocal (netadr_t adr);
|
||||
|
|
257
fteqtv/qw.c
257
fteqtv/qw.c
|
@ -23,6 +23,19 @@ 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_DefaultMovevars(movevars_t *vars)
|
||||
{
|
||||
vars->gravity = 800;
|
||||
vars->maxspeed = 320;
|
||||
vars->spectatormaxspeed = 500;
|
||||
vars->accelerate = 10;
|
||||
vars->airaccelerate = 0.7f;
|
||||
vars->waterfriction = 4;
|
||||
vars->entgrav = 1;
|
||||
vars->stopspeed = 10;
|
||||
vars->wateraccelerate = 10;
|
||||
vars->friction = 4;
|
||||
}
|
||||
|
||||
|
||||
void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum);
|
||||
|
@ -194,6 +207,7 @@ SOCKET QW_InitUDPSocket(int port)
|
|||
|
||||
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag)
|
||||
{
|
||||
movevars_t movevars;
|
||||
WriteByte(msg, svc_serverdata);
|
||||
WriteLong(msg, PROTOCOL_VERSION);
|
||||
WriteLong(msg, servercount);
|
||||
|
@ -211,16 +225,17 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
|
|||
|
||||
|
||||
// get the movevars
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
WriteFloat(msg, 0);
|
||||
QTV_DefaultMovevars(&movevars);
|
||||
WriteFloat(msg, movevars.gravity);
|
||||
WriteFloat(msg, movevars.stopspeed);
|
||||
WriteFloat(msg, movevars.maxspeed);
|
||||
WriteFloat(msg, movevars.spectatormaxspeed);
|
||||
WriteFloat(msg, movevars.accelerate);
|
||||
WriteFloat(msg, movevars.airaccelerate);
|
||||
WriteFloat(msg, movevars.wateraccelerate);
|
||||
WriteFloat(msg, movevars.friction);
|
||||
WriteFloat(msg, movevars.waterfriction);
|
||||
WriteFloat(msg, movevars.entgrav);
|
||||
|
||||
|
||||
|
||||
|
@ -663,6 +678,23 @@ void NewClient(cluster_t *cluster, viewer_t *viewer)
|
|||
QW_PrintfToViewer(viewer, "Type admin for the admin menu\n");
|
||||
}
|
||||
|
||||
void ParseUserInfo(viewer_t *viewer)
|
||||
{
|
||||
float rate;
|
||||
char temp[64];
|
||||
Info_ValueForKey(viewer->userinfo, "name", viewer->name, sizeof(viewer->name));
|
||||
|
||||
Info_ValueForKey(viewer->userinfo, "rate", temp, sizeof(temp));
|
||||
rate = atof(temp);
|
||||
if (!rate)
|
||||
rate = 2500;
|
||||
if (rate < 250)
|
||||
rate = 250;
|
||||
if (rate > 10000)
|
||||
rate = 10000;
|
||||
viewer->netchan.rate = 1000.0f / rate;
|
||||
}
|
||||
|
||||
void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
||||
{
|
||||
sv_t *initialserver;
|
||||
|
@ -734,8 +766,9 @@ void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
|||
|
||||
cluster->numviewers++;
|
||||
|
||||
strcpy(viewer->name, "unnamed");
|
||||
sprintf(viewer->userinfo, "\\name\\%s", viewer->name);
|
||||
sprintf(viewer->userinfo, "\\name\\%s", "unnamed");
|
||||
|
||||
ParseUserInfo(viewer);
|
||||
|
||||
NewClient(cluster, viewer);
|
||||
|
||||
|
@ -794,8 +827,8 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
|||
|
||||
cluster->numviewers++;
|
||||
|
||||
Info_ValueForKey(infostring, "name", viewer->name, sizeof(viewer->name));
|
||||
strncpy(viewer->userinfo, infostring, sizeof(viewer->userinfo)-1);
|
||||
ParseUserInfo(viewer);
|
||||
|
||||
Netchan_OutOfBandPrint(cluster, cluster->qwdsocket, *addr, "j");
|
||||
|
||||
|
@ -1215,11 +1248,21 @@ void SendLocalPlayerState(sv_t *tv, viewer_t *v, int playernum, netmsg_t *msg)
|
|||
}
|
||||
else
|
||||
{
|
||||
WriteShort(msg, 0);
|
||||
flags = 0;
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
if ((int)v->velocity[j])
|
||||
flags |= (PF_VELOCITY1<<j);
|
||||
|
||||
WriteShort(msg, flags);
|
||||
WriteShort(msg, v->origin[0]*8);
|
||||
WriteShort(msg, v->origin[1]*8);
|
||||
WriteShort(msg, v->origin[2]*8);
|
||||
WriteByte(msg, 0);
|
||||
|
||||
for (j=0 ; j<3 ; j++)
|
||||
if (flags & (PF_VELOCITY1<<j) )
|
||||
WriteShort (msg, v->velocity[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1821,7 +1864,7 @@ void UpdateStats(sv_t *qtv, viewer_t *v)
|
|||
|
||||
if (qtv && qtv->controller == v)
|
||||
stats = qtv->players[qtv->thisplayer].stats;
|
||||
else if (v->trackplayer != -1 || !qtv)
|
||||
else if (v->trackplayer == -1 || !qtv)
|
||||
stats = nullstats;
|
||||
else
|
||||
stats = qtv->players[v->trackplayer].stats;
|
||||
|
@ -1892,49 +1935,48 @@ int Prespawn(sv_t *qtv, int curmsgsize, netmsg_t *msg, int bufnum, int thisplaye
|
|||
return r;
|
||||
}
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#include <math.h>
|
||||
void AngleVectors (short angles[3], float *forward, float *right, float *up)
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[1] * (M_PI*2 / 65535);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[0] * (M_PI*2 / 65535);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[2] * (M_PI*2 / 65535);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = cp*sy;
|
||||
forward[2] = -sp;
|
||||
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
||||
right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
||||
right[2] = -1*sr*cp;
|
||||
up[0] = (cr*sp*cy+-sr*-sy);
|
||||
up[1] = (cr*sp*sy+-sr*cy);
|
||||
up[2] = cr*cp;
|
||||
}
|
||||
|
||||
void PMove(viewer_t *v, usercmd_t *cmd)
|
||||
{
|
||||
int i;
|
||||
float fwd[3], rgt[3], up[3];
|
||||
sv_t *qtv;
|
||||
pmove_t pmove;
|
||||
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;
|
||||
|
||||
v->velocity[0] = v->server->players[v->server->thisplayer].current.velocity[2]/8.0f;
|
||||
v->velocity[1] = v->server->players[v->server->thisplayer].current.velocity[2]/8.0f;
|
||||
v->velocity[2] = v->server->players[v->server->thisplayer].current.velocity[2]/8.0f;
|
||||
return;
|
||||
}
|
||||
AngleVectors(cmd->angles, fwd, rgt, up);
|
||||
pmove.origin[0] = v->origin[0];
|
||||
pmove.origin[1] = v->origin[1];
|
||||
pmove.origin[2] = v->origin[2];
|
||||
|
||||
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);
|
||||
pmove.velocity[0] = v->velocity[0];
|
||||
pmove.velocity[1] = v->velocity[1];
|
||||
pmove.velocity[2] = v->velocity[2];
|
||||
|
||||
pmove.cmd = *cmd;
|
||||
qtv = v->server;
|
||||
if (qtv)
|
||||
{
|
||||
pmove.movevars = qtv->movevars;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTV_DefaultMovevars(&pmove.movevars);
|
||||
}
|
||||
PM_PlayerMove(&pmove);
|
||||
|
||||
v->origin[0] = pmove.origin[0];
|
||||
v->origin[1] = pmove.origin[1];
|
||||
v->origin[2] = pmove.origin[2];
|
||||
|
||||
v->velocity[0] = pmove.velocity[0];
|
||||
v->velocity[1] = pmove.velocity[1];
|
||||
v->velocity[2] = pmove.velocity[2];
|
||||
}
|
||||
|
||||
void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean noupwards)
|
||||
|
@ -2177,6 +2219,13 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
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_SetMenu(v, MENU_SERVERS);
|
||||
}
|
||||
else if (!strncmp(message, ".admin", 6))
|
||||
{
|
||||
if (!*cluster->adminpassword)
|
||||
|
@ -2291,6 +2340,37 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
{
|
||||
QW_StuffcmdToViewer(v, "cmd say \".admin\"\n");
|
||||
}
|
||||
else if (!strncmp(message, ".clients", 8))
|
||||
{
|
||||
viewer_t *ov;
|
||||
int skipfirst = 0;
|
||||
int printable = 30;
|
||||
int remaining = 0;
|
||||
for (ov = cluster->viewers; ov; ov = ov->next)
|
||||
{
|
||||
if (skipfirst > 0)
|
||||
{
|
||||
skipfirst--;
|
||||
}
|
||||
else if (printable > 0)
|
||||
{
|
||||
printable--;
|
||||
if (ov->server)
|
||||
{
|
||||
if (ov->server->controller == ov)
|
||||
QW_PrintfToViewer(v, "%s: %s\n", ov->name, ov->server->server);
|
||||
else
|
||||
QW_PrintfToViewer(v, "%s: %s\n", ov->name, ov->server->server);
|
||||
}
|
||||
else
|
||||
QW_PrintfToViewer(v, "%s: %s\n", ov->name, "None");
|
||||
}
|
||||
else
|
||||
remaining++;
|
||||
}
|
||||
if (remaining)
|
||||
QW_PrintfToViewer(v, "%i clients not shown\n", remaining);
|
||||
}
|
||||
else if (!strncmp(message, "proxy:menu up", 13))
|
||||
{
|
||||
v->menuop -= 1;
|
||||
|
@ -2380,31 +2460,41 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
|||
}
|
||||
else
|
||||
{
|
||||
viewer_t *ov;
|
||||
if (cluster->notalking)
|
||||
return;
|
||||
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
for (ov = cluster->viewers; ov; ov = ov->next)
|
||||
{
|
||||
if (ov->server != v->server)
|
||||
continue;
|
||||
|
||||
WriteByte(&msg, svc_print);
|
||||
WriteByte(&msg, 3); //PRINT_CHAT
|
||||
WriteString2(&msg, v->name);
|
||||
WriteString2(&msg, "\x8d ");
|
||||
WriteString2(&msg, message);
|
||||
WriteString(&msg, "\n");
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
|
||||
Broadcast(cluster, msg.data, msg.cursize, QW);
|
||||
WriteByte(&msg, svc_print);
|
||||
|
||||
|
||||
InitNetMsg(&msg, buf, sizeof(buf));
|
||||
if (ov->netchan.isnqprotocol)
|
||||
WriteByte(&msg, 1);
|
||||
else
|
||||
{
|
||||
if (ov->conmenussupported)
|
||||
{
|
||||
WriteByte(&msg, 3); //PRINT_CHAT
|
||||
WriteString2(&msg, "^s^5");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(&msg, 3); //PRINT_CHAT
|
||||
}
|
||||
}
|
||||
|
||||
WriteByte(&msg, svc_print);
|
||||
WriteByte(&msg, 1);
|
||||
WriteString2(&msg, v->name);
|
||||
WriteString2(&msg, "\x8d ");
|
||||
WriteString2(&msg, message);
|
||||
WriteString(&msg, "\n");
|
||||
WriteString2(&msg, v->name);
|
||||
WriteString2(&msg, "\x8d ");
|
||||
WriteString2(&msg, message);
|
||||
WriteString(&msg, "\n");
|
||||
|
||||
Broadcast(cluster, msg.data, msg.cursize, NQ);
|
||||
SendBufferToViewer(ov, msg.data, msg.cursize, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2493,9 +2583,39 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
WriteByte (&msg, 2);
|
||||
SendBufferToViewer(v, msg.data, msg.cursize, true);
|
||||
}
|
||||
|
||||
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));
|
||||
ParseUserInfo(v);
|
||||
// Info_ValueForKey(v->userinfo, "name", v->name, sizeof(v->name));
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
SendClientCommand(v->server, "%s", buf);
|
||||
}
|
||||
|
||||
else if (!strncmp(buf, "name ", 5))
|
||||
{
|
||||
Q_strncpyz(v->name, buf+5, sizeof(v->name));
|
||||
Info_SetValueForStarKey(v->userinfo, "name", buf+5, sizeof(v->userinfo));
|
||||
ParseUserInfo(v);
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
SendClientCommand(v->server, "setinfo name \"%s\"", v->name);
|
||||
}
|
||||
else if (!strncmp(buf, "color ", 6))
|
||||
{
|
||||
|
@ -2803,7 +2923,8 @@ void ParseQWC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
}
|
||||
|
||||
Info_SetValueForStarKey(v->userinfo, arg[1], arg[2], sizeof(v->userinfo));
|
||||
Info_ValueForKey(v->userinfo, "name", v->name, sizeof(v->name));
|
||||
ParseUserInfo(v);
|
||||
// Info_ValueForKey(v->userinfo, "name", v->name, sizeof(v->name));
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
SendClientCommand(v->server, "%s", buf);
|
||||
|
@ -3465,6 +3586,8 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
|||
{
|
||||
v->maysend = (v->nextpacket < cluster->curtime);
|
||||
}
|
||||
if (!Netchan_CanPacket(&v->netchan))
|
||||
continue;
|
||||
if (v->maysend) //don't send incompleate connection data.
|
||||
{
|
||||
v->nextpacket = cluster->curtime + 1000/NQ_PACKETS_PER_SECOND;
|
||||
|
|
|
@ -410,7 +410,7 @@ qboolean Net_ConnectToServer(sv_t *qtv, char *ip)
|
|||
{
|
||||
qtv->usequkeworldprotocols = false;
|
||||
|
||||
if (!strncmp(ip, "file:", 5))
|
||||
if (!strncmp(ip, "file:", 5) || !strncmp(ip, "demo:", 5))
|
||||
{
|
||||
qtv->sourcesock = INVALID_SOCKET;
|
||||
qtv->file = fopen(ip+5, "rb");
|
||||
|
@ -1433,6 +1433,13 @@ void QTV_Run(sv_t *qtv)
|
|||
return;
|
||||
}
|
||||
else if (!strcmp(start, "PERROR"))
|
||||
{
|
||||
Sys_Printf(qtv->cluster, "\nQTV server error: %s\n\n", colon);
|
||||
qtv->drop = true;
|
||||
qtv->buffersize = 0;
|
||||
return;
|
||||
}
|
||||
else if (!strcmp(start, "TERROR"))
|
||||
{ //we don't support compression, we didn't ask for it.
|
||||
Sys_Printf(qtv->cluster, "\nQTV server error: %s\n\n", colon);
|
||||
qtv->drop = true;
|
||||
|
@ -1440,9 +1447,12 @@ void QTV_Run(sv_t *qtv)
|
|||
return;
|
||||
}
|
||||
else if (!strcmp(start, "PRINT"))
|
||||
{ //we don't support compression, we didn't ask for it.
|
||||
Sys_Printf(qtv->cluster, "QTV server: \n");
|
||||
return;
|
||||
{
|
||||
Sys_Printf(qtv->cluster, "QTV server: %s\n", colon);
|
||||
}
|
||||
else if (!strcmp(start, "BEGIN"))
|
||||
{
|
||||
qtv->parsingqtvheader = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1455,15 +1465,18 @@ void QTV_Run(sv_t *qtv)
|
|||
qtv->buffersize -= length;
|
||||
memmove(qtv->buffer, qtv->buffer + length, qtv->buffersize);
|
||||
|
||||
if (*authmethod == '\0')
|
||||
qtv->parsingqtvheader = false;
|
||||
else
|
||||
if (*authmethod)
|
||||
{ //we need to send a challenge response now.
|
||||
Net_SendQTVConnectionRequest(qtv, authmethod, challenge);
|
||||
}
|
||||
|
||||
if (qtv->parsingqtvheader)
|
||||
return;
|
||||
}
|
||||
else if (qtv->parsingqtvheader)
|
||||
{
|
||||
Sys_Printf(qtv->cluster, "QTV server sent no begin command - assuming incompatable\n\n", colon);
|
||||
qtv->drop = true;
|
||||
qtv->buffersize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
qtv->parsetime = Sys_Milliseconds() + BUFFERTIME*1000;
|
||||
if (!qtv->usequkeworldprotocols)
|
||||
|
|
Loading…
Reference in a new issue