mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-14 00:10:46 +00:00
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
|
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
|
qtv: $(OBJS) qtv.h
|
||||||
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@.db -lm
|
$(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;
|
} usercmd_t;
|
||||||
extern const usercmd_t nullcmd;
|
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
|
#define MAX_BACK_BUFFERS 16
|
||||||
typedef struct sv_s sv_t;
|
typedef struct sv_s sv_t;
|
||||||
typedef struct cluster_s cluster_t;
|
typedef struct cluster_s cluster_t;
|
||||||
|
@ -384,7 +414,7 @@ typedef struct viewer_s {
|
||||||
struct viewer_s *next;
|
struct viewer_s *next;
|
||||||
|
|
||||||
char name[32];
|
char name[32];
|
||||||
char userinfo[256];
|
char userinfo[1024];
|
||||||
|
|
||||||
int lost; //packets
|
int lost; //packets
|
||||||
usercmd_t ucmds[3];
|
usercmd_t ucmds[3];
|
||||||
|
@ -392,7 +422,8 @@ typedef struct viewer_s {
|
||||||
|
|
||||||
int settime; //the time that we last told the client.
|
int settime; //the time that we last told the client.
|
||||||
|
|
||||||
float origin[3];
|
vec3_t velocity;
|
||||||
|
vec3_t origin;
|
||||||
|
|
||||||
int isadmin;
|
int isadmin;
|
||||||
char expectcommand[16];
|
char expectcommand[16];
|
||||||
|
@ -474,18 +505,7 @@ struct sv_s {
|
||||||
|
|
||||||
char gamedir[MAX_QPATH];
|
char gamedir[MAX_QPATH];
|
||||||
char mapname[256];
|
char mapname[256];
|
||||||
struct {
|
movevars_t movevars;
|
||||||
float gravity;
|
|
||||||
float maxspeed;
|
|
||||||
float spectatormaxspeed;
|
|
||||||
float accelerate;
|
|
||||||
float airaccelerate;
|
|
||||||
float waterfriction;
|
|
||||||
float entgrav;
|
|
||||||
float stopspeed;
|
|
||||||
float wateraccelerate;
|
|
||||||
float friction;
|
|
||||||
} movevars;
|
|
||||||
int cdtrack;
|
int cdtrack;
|
||||||
entity_t entity[MAX_ENTITIES];
|
entity_t entity[MAX_ENTITIES];
|
||||||
frame_t frame[MAX_ENTITY_FRAMES];
|
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_PrintfToViewer(viewer_t *v, char *format, ...);
|
||||||
void QW_StuffcmdToViewer(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_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qboolean isclient);
|
||||||
void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...);
|
void Netchan_OutOfBandPrint (cluster_t *cluster, SOCKET sock, netadr_t adr, char *format, ...);
|
||||||
int Netchan_IsLocal (netadr_t adr);
|
int Netchan_IsLocal (netadr_t adr);
|
||||||
|
|
247
fteqtv/qw.c
247
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 ConnectionlessModelList[] = {{""}, {"maps/start.bsp"}, {"progs/player.mdl"}, {""}};
|
||||||
static const filename_t ConnectionlessSoundList[] = {{""}, {""}};
|
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);
|
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)
|
void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qboolean spectatorflag)
|
||||||
{
|
{
|
||||||
|
movevars_t movevars;
|
||||||
WriteByte(msg, svc_serverdata);
|
WriteByte(msg, svc_serverdata);
|
||||||
WriteLong(msg, PROTOCOL_VERSION);
|
WriteLong(msg, PROTOCOL_VERSION);
|
||||||
WriteLong(msg, servercount);
|
WriteLong(msg, servercount);
|
||||||
|
@ -211,16 +225,17 @@ void BuildServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount, qbo
|
||||||
|
|
||||||
|
|
||||||
// get the movevars
|
// get the movevars
|
||||||
WriteFloat(msg, 0);
|
QTV_DefaultMovevars(&movevars);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.gravity);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.stopspeed);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.maxspeed);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.spectatormaxspeed);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.accelerate);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.airaccelerate);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.wateraccelerate);
|
||||||
WriteFloat(msg, 0);
|
WriteFloat(msg, movevars.friction);
|
||||||
WriteFloat(msg, 0);
|
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");
|
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)
|
void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
||||||
{
|
{
|
||||||
sv_t *initialserver;
|
sv_t *initialserver;
|
||||||
|
@ -734,8 +766,9 @@ void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
||||||
|
|
||||||
cluster->numviewers++;
|
cluster->numviewers++;
|
||||||
|
|
||||||
strcpy(viewer->name, "unnamed");
|
sprintf(viewer->userinfo, "\\name\\%s", "unnamed");
|
||||||
sprintf(viewer->userinfo, "\\name\\%s", viewer->name);
|
|
||||||
|
ParseUserInfo(viewer);
|
||||||
|
|
||||||
NewClient(cluster, viewer);
|
NewClient(cluster, viewer);
|
||||||
|
|
||||||
|
@ -794,8 +827,8 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
||||||
|
|
||||||
cluster->numviewers++;
|
cluster->numviewers++;
|
||||||
|
|
||||||
Info_ValueForKey(infostring, "name", viewer->name, sizeof(viewer->name));
|
|
||||||
strncpy(viewer->userinfo, infostring, sizeof(viewer->userinfo)-1);
|
strncpy(viewer->userinfo, infostring, sizeof(viewer->userinfo)-1);
|
||||||
|
ParseUserInfo(viewer);
|
||||||
|
|
||||||
Netchan_OutOfBandPrint(cluster, cluster->qwdsocket, *addr, "j");
|
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
|
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[0]*8);
|
||||||
WriteShort(msg, v->origin[1]*8);
|
WriteShort(msg, v->origin[1]*8);
|
||||||
WriteShort(msg, v->origin[2]*8);
|
WriteShort(msg, v->origin[2]*8);
|
||||||
WriteByte(msg, 0);
|
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)
|
if (qtv && qtv->controller == v)
|
||||||
stats = qtv->players[qtv->thisplayer].stats;
|
stats = qtv->players[qtv->thisplayer].stats;
|
||||||
else if (v->trackplayer != -1 || !qtv)
|
else if (v->trackplayer == -1 || !qtv)
|
||||||
stats = nullstats;
|
stats = nullstats;
|
||||||
else
|
else
|
||||||
stats = qtv->players[v->trackplayer].stats;
|
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;
|
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)
|
void PMove(viewer_t *v, usercmd_t *cmd)
|
||||||
{
|
{
|
||||||
int i;
|
sv_t *qtv;
|
||||||
float fwd[3], rgt[3], up[3];
|
pmove_t pmove;
|
||||||
if (v->server && v->server->controller == v)
|
if (v->server && v->server->controller == v)
|
||||||
{
|
{
|
||||||
v->origin[0] = v->server->players[v->server->thisplayer].current.origin[0]/8.0f;
|
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[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->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;
|
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++)
|
pmove.velocity[0] = v->velocity[0];
|
||||||
v->origin[i] += (cmd->forwardmove*fwd[i] + cmd->sidemove*rgt[i] + cmd->upmove*up[i])*(cmd->msec/1000.0f);
|
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)
|
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_SetViewersServer(v, NULL);
|
||||||
QW_SetMenu(v, MENU_SERVERS);
|
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))
|
else if (!strncmp(message, ".admin", 6))
|
||||||
{
|
{
|
||||||
if (!*cluster->adminpassword)
|
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");
|
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))
|
else if (!strncmp(message, "proxy:menu up", 13))
|
||||||
{
|
{
|
||||||
v->menuop -= 1;
|
v->menuop -= 1;
|
||||||
|
@ -2380,31 +2460,41 @@ void QTV_Say(cluster_t *cluster, sv_t *qtv, viewer_t *v, char *message, qboolean
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
viewer_t *ov;
|
||||||
if (cluster->notalking)
|
if (cluster->notalking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InitNetMsg(&msg, buf, sizeof(buf));
|
for (ov = cluster->viewers; ov; ov = ov->next)
|
||||||
|
{
|
||||||
WriteByte(&msg, svc_print);
|
if (ov->server != v->server)
|
||||||
WriteByte(&msg, 3); //PRINT_CHAT
|
continue;
|
||||||
WriteString2(&msg, v->name);
|
|
||||||
WriteString2(&msg, "\x8d ");
|
|
||||||
WriteString2(&msg, message);
|
|
||||||
WriteString(&msg, "\n");
|
|
||||||
|
|
||||||
Broadcast(cluster, msg.data, msg.cursize, QW);
|
|
||||||
|
|
||||||
|
|
||||||
InitNetMsg(&msg, buf, sizeof(buf));
|
InitNetMsg(&msg, buf, sizeof(buf));
|
||||||
|
|
||||||
WriteByte(&msg, svc_print);
|
WriteByte(&msg, svc_print);
|
||||||
|
|
||||||
|
if (ov->netchan.isnqprotocol)
|
||||||
WriteByte(&msg, 1);
|
WriteByte(&msg, 1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ov->conmenussupported)
|
||||||
|
{
|
||||||
|
WriteByte(&msg, 3); //PRINT_CHAT
|
||||||
|
WriteString2(&msg, "^s^5");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteByte(&msg, 3); //PRINT_CHAT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WriteString2(&msg, v->name);
|
WriteString2(&msg, v->name);
|
||||||
WriteString2(&msg, "\x8d ");
|
WriteString2(&msg, "\x8d ");
|
||||||
WriteString2(&msg, message);
|
WriteString2(&msg, message);
|
||||||
WriteString(&msg, "\n");
|
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);
|
WriteByte (&msg, 2);
|
||||||
SendBufferToViewer(v, msg.data, msg.cursize, true);
|
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))
|
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))
|
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_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)
|
if (v->server && v->server->controller == v)
|
||||||
SendClientCommand(v->server, "%s", buf);
|
SendClientCommand(v->server, "%s", buf);
|
||||||
|
@ -3465,6 +3586,8 @@ void QW_UpdateUDPStuff(cluster_t *cluster)
|
||||||
{
|
{
|
||||||
v->maysend = (v->nextpacket < cluster->curtime);
|
v->maysend = (v->nextpacket < cluster->curtime);
|
||||||
}
|
}
|
||||||
|
if (!Netchan_CanPacket(&v->netchan))
|
||||||
|
continue;
|
||||||
if (v->maysend) //don't send incompleate connection data.
|
if (v->maysend) //don't send incompleate connection data.
|
||||||
{
|
{
|
||||||
v->nextpacket = cluster->curtime + 1000/NQ_PACKETS_PER_SECOND;
|
v->nextpacket = cluster->curtime + 1000/NQ_PACKETS_PER_SECOND;
|
||||||
|
|
|
@ -410,7 +410,7 @@ qboolean Net_ConnectToServer(sv_t *qtv, char *ip)
|
||||||
{
|
{
|
||||||
qtv->usequkeworldprotocols = false;
|
qtv->usequkeworldprotocols = false;
|
||||||
|
|
||||||
if (!strncmp(ip, "file:", 5))
|
if (!strncmp(ip, "file:", 5) || !strncmp(ip, "demo:", 5))
|
||||||
{
|
{
|
||||||
qtv->sourcesock = INVALID_SOCKET;
|
qtv->sourcesock = INVALID_SOCKET;
|
||||||
qtv->file = fopen(ip+5, "rb");
|
qtv->file = fopen(ip+5, "rb");
|
||||||
|
@ -1433,6 +1433,13 @@ void QTV_Run(sv_t *qtv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!strcmp(start, "PERROR"))
|
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.
|
{ //we don't support compression, we didn't ask for it.
|
||||||
Sys_Printf(qtv->cluster, "\nQTV server error: %s\n\n", colon);
|
Sys_Printf(qtv->cluster, "\nQTV server error: %s\n\n", colon);
|
||||||
qtv->drop = true;
|
qtv->drop = true;
|
||||||
|
@ -1440,9 +1447,12 @@ void QTV_Run(sv_t *qtv)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!strcmp(start, "PRINT"))
|
else if (!strcmp(start, "PRINT"))
|
||||||
{ //we don't support compression, we didn't ask for it.
|
{
|
||||||
Sys_Printf(qtv->cluster, "QTV server: \n");
|
Sys_Printf(qtv->cluster, "QTV server: %s\n", colon);
|
||||||
return;
|
}
|
||||||
|
else if (!strcmp(start, "BEGIN"))
|
||||||
|
{
|
||||||
|
qtv->parsingqtvheader = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1455,15 +1465,18 @@ void QTV_Run(sv_t *qtv)
|
||||||
qtv->buffersize -= length;
|
qtv->buffersize -= length;
|
||||||
memmove(qtv->buffer, qtv->buffer + length, qtv->buffersize);
|
memmove(qtv->buffer, qtv->buffer + length, qtv->buffersize);
|
||||||
|
|
||||||
if (*authmethod == '\0')
|
if (*authmethod)
|
||||||
qtv->parsingqtvheader = false;
|
|
||||||
else
|
|
||||||
{ //we need to send a challenge response now.
|
{ //we need to send a challenge response now.
|
||||||
Net_SendQTVConnectionRequest(qtv, authmethod, challenge);
|
Net_SendQTVConnectionRequest(qtv, authmethod, challenge);
|
||||||
}
|
|
||||||
|
|
||||||
if (qtv->parsingqtvheader)
|
|
||||||
return;
|
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;
|
qtv->parsetime = Sys_Milliseconds() + BUFFERTIME*1000;
|
||||||
if (!qtv->usequkeworldprotocols)
|
if (!qtv->usequkeworldprotocols)
|
||||||
|
|
Loading…
Reference in a new issue