mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
mvd recording :) (thanks to qwex 0.165b and highlander)
This commit is contained in:
parent
30c8646e70
commit
212e40b54a
11 changed files with 532 additions and 241 deletions
|
@ -297,7 +297,7 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
int num_entities;
|
||||
entity_state_t entities[MAX_PACKET_ENTITIES];
|
||||
entity_state_t *entities;
|
||||
} packet_entities_t;
|
||||
|
||||
typedef struct usercmd_s
|
||||
|
|
|
@ -249,11 +249,13 @@ typedef struct
|
|||
{
|
||||
double active;
|
||||
double idle;
|
||||
double demo;
|
||||
int count;
|
||||
int packets;
|
||||
|
||||
double latched_active;
|
||||
double latched_idle;
|
||||
double latched_demo;
|
||||
int latched_packets;
|
||||
} svstats_t;
|
||||
|
||||
|
@ -510,11 +512,12 @@ void SV_SetMoveVars(void);
|
|||
void SV_Print (const char *fmt, va_list args);
|
||||
void SV_Printf (const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
void SV_SendClientMessages (void);
|
||||
void SV_SendDemoMessage(void);
|
||||
|
||||
void SV_Multicast (const vec3_t origin, int to);
|
||||
void SV_StartSound (struct edict_s *entity, int channel, const char *sample,
|
||||
int volume, float attenuation);
|
||||
void SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...) __attribute__((format(printf,3,4)));
|
||||
void SV_ClientPrintf (int recorder, client_t *cl, int level, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
void SV_BroadcastPrintf (int level, const char *fmt, ...) __attribute__((format(printf,2,3)));
|
||||
void SV_BroadcastCommand (const char *fmt, ...) __attribute__((format(printf,1,2)));
|
||||
void SV_SendMessagesToAll (void);
|
||||
|
@ -543,7 +546,8 @@ void SV_Status_f (void);
|
|||
//
|
||||
// sv_ents.c
|
||||
//
|
||||
void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg);
|
||||
void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg,
|
||||
qboolean recorder);
|
||||
|
||||
//
|
||||
// sv_nchan.c
|
||||
|
|
|
@ -63,12 +63,7 @@ typedef struct {
|
|||
} demo_client_t;
|
||||
|
||||
typedef struct {
|
||||
qboolean allowoverflow; // if false, do a Sys_Error
|
||||
qboolean overflowed; // set to true if the buffer size
|
||||
// failed
|
||||
byte *data;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
sizebuf_t sz;
|
||||
int bufsize;
|
||||
header_t *h;
|
||||
} demobuf_t;
|
||||
|
@ -112,5 +107,27 @@ typedef struct {
|
|||
} demo_t;
|
||||
|
||||
extern demo_t demo;
|
||||
extern struct cvar_s *sv_demoUseCache;
|
||||
extern struct cvar_s *sv_demoCacheSize;
|
||||
extern struct cvar_s *sv_demoMaxDirSize;
|
||||
extern struct cvar_s *sv_demoDir;
|
||||
extern struct cvar_s *sv_demofps;
|
||||
extern struct cvar_s *sv_demoPings;
|
||||
extern struct cvar_s *sv_demoNoVis;
|
||||
extern struct cvar_s *sv_demoMaxSize;
|
||||
extern struct cvar_s *sv_demoPrefix;
|
||||
extern struct cvar_s *sv_demoSuffix;
|
||||
extern struct cvar_s *sv_onrecordfinish;
|
||||
extern struct cvar_s *sv_ondemoremove;
|
||||
extern struct cvar_s *sv_demotxt;
|
||||
extern struct cvar_s *serverdemo;
|
||||
|
||||
void DemoWrite_Begin (byte type, int to, int size);
|
||||
void SV_DemoWritePackets (int num);
|
||||
void SV_Stop_f (void);
|
||||
void SV_Stop (int reason);
|
||||
void DemoSetMsgBuf (demobuf_t * prev, demobuf_t * cur);
|
||||
void Demo_Init (void);
|
||||
void SV_DemoPings (void);
|
||||
|
||||
#endif//__sv_demo_h
|
||||
|
|
|
@ -181,6 +181,7 @@ static int cl_usleep_cache;
|
|||
|
||||
client_static_t cls;
|
||||
client_state_t cl;
|
||||
entity_state_t cl_entities[UPDATE_BACKUP][MAX_PACKET_ENTITIES];
|
||||
|
||||
entity_state_t cl_baselines[MAX_EDICTS];
|
||||
efrag_t cl_efrags[MAX_EFRAGS];
|
||||
|
@ -388,11 +389,16 @@ CL_Rcon_f (void)
|
|||
void
|
||||
CL_ClearState (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
S_StopAllSounds (true);
|
||||
|
||||
// wipe the entire cl structure
|
||||
Info_Destroy (cl.serverinfo);
|
||||
memset (&cl, 0, sizeof (cl));
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
cl.frames[i].packet_entities.entities = cl_entities[i];
|
||||
memset (cl_entities, 0, sizeof (cl_entities));
|
||||
cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING);
|
||||
|
||||
CL_Init_Entity (&cl.viewent);
|
||||
|
|
|
@ -53,6 +53,7 @@ static const char rcsid[] =
|
|||
#include "bothdefs.h"
|
||||
#include "compat.h"
|
||||
#include "server.h"
|
||||
#include "sv_demo.h"
|
||||
#include "sv_progs.h"
|
||||
|
||||
qboolean sv_allow_cheats;
|
||||
|
@ -265,9 +266,9 @@ SV_God_f (void)
|
|||
|
||||
SVfloat (sv_player, flags) = (int) SVfloat (sv_player, flags) ^ FL_GODMODE;
|
||||
if (!((int) SVfloat (sv_player, flags) & FL_GODMODE))
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "godmode OFF\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "godmode OFF\n");
|
||||
else
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "godmode ON\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "godmode ON\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -284,10 +285,10 @@ SV_Noclip_f (void)
|
|||
|
||||
if (SVfloat (sv_player, movetype) != MOVETYPE_NOCLIP) {
|
||||
SVfloat (sv_player, movetype) = MOVETYPE_NOCLIP;
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "noclip ON\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "noclip ON\n");
|
||||
} else {
|
||||
SVfloat (sv_player, movetype) = MOVETYPE_WALK;
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "noclip OFF\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "noclip OFF\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,6 +378,9 @@ SV_Map_f (void)
|
|||
}
|
||||
Qclose (f);
|
||||
|
||||
if (sv.demorecording)
|
||||
SV_Stop_f ();
|
||||
|
||||
SV_BroadcastCommand ("changing\n");
|
||||
SV_SendMessagesToAll ();
|
||||
|
||||
|
@ -417,7 +421,8 @@ SV_Kick_f (void)
|
|||
SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked\n", cl->name);
|
||||
// print directly, because the dropped client won't get the
|
||||
// SV_BroadcastPrintf message
|
||||
SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked from the game\n");
|
||||
SV_ClientPrintf (1, cl, PRINT_HIGH,
|
||||
"You were kicked from the game\n");
|
||||
SV_DropClient (cl);
|
||||
return;
|
||||
}
|
||||
|
@ -431,25 +436,27 @@ SV_Status_f (void)
|
|||
{
|
||||
int i;
|
||||
client_t *cl;
|
||||
float cpu, avg, pak;
|
||||
float cpu, avg, pak, demo = 0;
|
||||
const char *s;
|
||||
|
||||
|
||||
cpu = (svs.stats.latched_active + svs.stats.latched_idle);
|
||||
if (cpu)
|
||||
if (cpu) {
|
||||
demo = 100 * svs.stats.latched_demo / cpu;
|
||||
cpu = 100 * svs.stats.latched_active / cpu;
|
||||
}
|
||||
avg = 1000 * svs.stats.latched_active / STATFRAMES;
|
||||
pak = (float) svs.stats.latched_packets / STATFRAMES;
|
||||
|
||||
SV_Printf ("net address : %s\n", NET_AdrToString (net_local_adr));
|
||||
SV_Printf ("cpu utilization : %3i%%\n", (int) cpu);
|
||||
SV_Printf ("cpu utilization : %3i%% (%3i%%)\n", (int) cpu, (int)demo);
|
||||
SV_Printf ("avg response time: %i ms\n", (int) avg);
|
||||
SV_Printf ("packets/frame : %5.2f\n", pak);
|
||||
|
||||
// min fps lat drp
|
||||
if (sv_redirected != RD_NONE) {
|
||||
// most remote clients are 40 columns
|
||||
// 0123456789012345678901234567890123456789
|
||||
// 0123456789012345678901234567890123456789
|
||||
SV_Printf ("name userid frags\n");
|
||||
SV_Printf (" address rate ping drop\n");
|
||||
SV_Printf (" ---------------- ---- ---- -----\n");
|
||||
|
@ -475,11 +482,11 @@ SV_Status_f (void)
|
|||
SV_Printf ("ZOMBIE\n");
|
||||
continue;
|
||||
}
|
||||
SV_Printf ("%4i %4i %5.2f\n", (int) (1000 * cl->netchan.frame_rate)
|
||||
, (int) SV_CalcPing (cl)
|
||||
,
|
||||
100.0 * cl->netchan.drop_count /
|
||||
cl->netchan.incoming_sequence);
|
||||
SV_Printf ("%4i %4i %5.2f\n",
|
||||
(int) (1000 * cl->netchan.frame_rate),
|
||||
(int) SV_CalcPing (cl),
|
||||
100.0 * cl->netchan.drop_count /
|
||||
cl->netchan.incoming_sequence);
|
||||
}
|
||||
} else {
|
||||
SV_Printf ("frags userid address name rate ping "
|
||||
|
@ -676,9 +683,9 @@ SV_Tell (const char *prefix)
|
|||
if (!cl->state)
|
||||
continue;
|
||||
if (cl->userid == uid) {
|
||||
SV_ClientPrintf(cl, PRINT_CHAT, "\n"); // bell
|
||||
SV_ClientPrintf(cl, PRINT_HIGH, "%s\n", text);
|
||||
SV_ClientPrintf(cl, PRINT_CHAT, "%s", ""); // bell
|
||||
SV_ClientPrintf (1, cl, PRINT_CHAT, "\n"); // bell
|
||||
SV_ClientPrintf (1, cl, PRINT_HIGH, "%s\n", text);
|
||||
SV_ClientPrintf (1, cl, PRINT_CHAT, "%s", ""); // bell
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -766,9 +773,15 @@ SV_ConSay (const char *prefix)
|
|||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) {
|
||||
if (client->state != cs_spawned) // kk just has !client->state
|
||||
continue;
|
||||
SV_ClientPrintf (client, PRINT_HIGH, "%s\n", text);
|
||||
SV_ClientPrintf (1, client, PRINT_HIGH, "%s\n", text);
|
||||
if (*prefix != 'I') // beep, except for Info says
|
||||
SV_ClientPrintf(client, PRINT_CHAT, "%s", "");
|
||||
SV_ClientPrintf (0, client, PRINT_CHAT, "%s", "");
|
||||
}
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text) + 3);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
|
||||
MSG_WriteString (&demo.dbuf->sz, text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,6 @@ static const char rcsid[] =
|
|||
|
||||
demo_t demo;
|
||||
|
||||
void DemoWrite_Begin (byte type, int to, int size);
|
||||
void SV_DemoWritePackets (int num);
|
||||
void SV_Stop_f (void);
|
||||
|
||||
#define MIN_DEMO_MEMORY 0x100000
|
||||
#define USACACHE (sv_demoUseCache->int_val && svs.demomemsize)
|
||||
#define DWRITE(a,b,d) dwrite((QFile *)d,a,b)
|
||||
|
@ -65,6 +61,9 @@ void SV_Stop_f (void);
|
|||
demobuffer->maxsize - demobuffer->end)
|
||||
|
||||
|
||||
|
||||
static int demo_max_size;
|
||||
static int demo_size;
|
||||
cvar_t *sv_demoUseCache;
|
||||
cvar_t *sv_demoCacheSize;
|
||||
cvar_t *sv_demoMaxDirSize;
|
||||
|
@ -73,9 +72,6 @@ cvar_t *sv_demofps;
|
|||
cvar_t *sv_demoPings;
|
||||
cvar_t *sv_demoNoVis;
|
||||
cvar_t *sv_demoMaxSize;
|
||||
|
||||
static int demo_max_size;
|
||||
static int demo_size;
|
||||
cvar_t *sv_demoPrefix;
|
||||
cvar_t *sv_demoSuffix;
|
||||
cvar_t *sv_onrecordfinish;
|
||||
|
@ -151,13 +147,13 @@ DemoSetMsgBuf (demobuf_t * prev, demobuf_t * cur)
|
|||
// fix the maxsize of previous msg buffer,
|
||||
// we won't be able to write there anymore
|
||||
if (prev != NULL)
|
||||
prev->maxsize = prev->bufsize;
|
||||
prev->sz.maxsize = prev->bufsize;
|
||||
|
||||
demo.dbuf = cur;
|
||||
memset (demo.dbuf, 0, sizeof (*demo.dbuf));
|
||||
|
||||
demo.dbuf->data = demobuffer->data + demobuffer->end;
|
||||
demo.dbuf->maxsize = MAXSIZE;
|
||||
demo.dbuf->sz.data = demobuffer->data + demobuffer->end;
|
||||
demo.dbuf->sz.maxsize = MAXSIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -176,7 +172,7 @@ SV_DemoWriteToDisk (int type, int to, float time)
|
|||
int size;
|
||||
sizebuf_t msg;
|
||||
|
||||
(byte *) p = demo.dbuf->data;
|
||||
(byte *) p = demo.dbuf->sz.data;
|
||||
demo.dbuf->h = NULL;
|
||||
|
||||
oldm = demo.dbuf->bufsize;
|
||||
|
@ -194,14 +190,14 @@ SV_DemoWriteToDisk (int type, int to, float time)
|
|||
SV_WriteDemoMessage (&msg, p->type, p->to, time);
|
||||
}
|
||||
// data is written so it need to be cleard from demobuf
|
||||
if (demo.dbuf->data != (byte *) p)
|
||||
memmove (demo.dbuf->data + size + header, demo.dbuf->data,
|
||||
(byte *) p - demo.dbuf->data);
|
||||
if (demo.dbuf->sz.data != (byte *) p)
|
||||
memmove (demo.dbuf->sz.data + size + header,
|
||||
demo.dbuf->sz.data, (byte *) p - demo.dbuf->sz.data);
|
||||
|
||||
demo.dbuf->bufsize -= size + header;
|
||||
demo.dbuf->data += size + header;
|
||||
demo.dbuf->sz.data += size + header;
|
||||
pos -= size + header;
|
||||
demo.dbuf->maxsize -= size + header;
|
||||
demo.dbuf->sz.maxsize -= size + header;
|
||||
demobuffer->start += size + header;
|
||||
}
|
||||
// move along
|
||||
|
@ -211,7 +207,7 @@ SV_DemoWriteToDisk (int type, int to, float time)
|
|||
if (demobuffer->start == demobuffer->last) {
|
||||
if (demobuffer->start == demobuffer->end) {
|
||||
demobuffer->end = 0; // demobuffer is empty
|
||||
demo.dbuf->data = demobuffer->data;
|
||||
demo.dbuf->sz.data = demobuffer->data;
|
||||
}
|
||||
// go back to begining of the buffer
|
||||
demobuffer->last = demobuffer->end;
|
||||
|
@ -231,13 +227,13 @@ DemoSetBuf (byte type, int to)
|
|||
header_t *p;
|
||||
int pos = 0;
|
||||
|
||||
(byte *) p = demo.dbuf->data;
|
||||
(byte *) p = demo.dbuf->sz.data;
|
||||
|
||||
while (pos < demo.dbuf->bufsize) {
|
||||
pos += header + p->size;
|
||||
|
||||
if (type == p->type && to == p->to && !p->full) {
|
||||
demo.dbuf->cursize = pos;
|
||||
demo.dbuf->sz.cursize = pos;
|
||||
demo.dbuf->h = p;
|
||||
return;
|
||||
}
|
||||
|
@ -252,7 +248,7 @@ DemoSetBuf (byte type, int to)
|
|||
p->full = 0;
|
||||
|
||||
demo.dbuf->bufsize += header;
|
||||
demo.dbuf->cursize = demo.dbuf->bufsize;
|
||||
demo.dbuf->sz.cursize = demo.dbuf->bufsize;
|
||||
demobuffer->end += header;
|
||||
demo.dbuf->h = p;
|
||||
}
|
||||
|
@ -265,11 +261,11 @@ DemoMoveBuf (void)
|
|||
demobuffer->last = demobuffer->end - demo.dbuf->bufsize;
|
||||
|
||||
// move buffer to the begining of demo buffer
|
||||
memmove (demobuffer->data, demo.dbuf->data, demo.dbuf->bufsize);
|
||||
demo.dbuf->data = demobuffer->data;
|
||||
memmove (demobuffer->data, demo.dbuf->sz.data, demo.dbuf->bufsize);
|
||||
demo.dbuf->sz.data = demobuffer->data;
|
||||
demobuffer->end = demo.dbuf->bufsize;
|
||||
demo.dbuf->h = NULL; // it will be setup again
|
||||
demo.dbuf->maxsize = MAXSIZE + demo.dbuf->bufsize;
|
||||
demo.dbuf->sz.maxsize = MAXSIZE + demo.dbuf->bufsize;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -279,7 +275,7 @@ DemoWrite_Begin (byte type, int to, int size)
|
|||
qboolean move = false;
|
||||
|
||||
// will it fit?
|
||||
while (demo.dbuf->bufsize + size + header > demo.dbuf->maxsize) {
|
||||
while (demo.dbuf->bufsize + size + header > demo.dbuf->sz.maxsize) {
|
||||
// if we reached the end of buffer move msgbuf to the begining
|
||||
if (!move && demobuffer->end > demobuffer->start)
|
||||
move = true;
|
||||
|
@ -299,9 +295,9 @@ DemoWrite_Begin (byte type, int to, int size)
|
|||
DemoSetBuf (type, to);
|
||||
}
|
||||
// we have to make room for new data
|
||||
if (demo.dbuf->cursize != demo.dbuf->bufsize) {
|
||||
p = demo.dbuf->data + demo.dbuf->cursize;
|
||||
memmove (p + size, p, demo.dbuf->bufsize - demo.dbuf->cursize);
|
||||
if (demo.dbuf->sz.cursize != demo.dbuf->bufsize) {
|
||||
p = demo.dbuf->sz.data + demo.dbuf->sz.cursize;
|
||||
memmove (p + size, p, demo.dbuf->bufsize - demo.dbuf->sz.cursize);
|
||||
}
|
||||
|
||||
demo.dbuf->bufsize += size;
|
||||
|
@ -568,7 +564,7 @@ SV_DemoWritePackets (int num)
|
|||
demo.lastwritten = demo.parsecount;
|
||||
|
||||
demo.dbuf = &demo.frames[demo.parsecount & DEMO_FRAMES_MASK].buf;
|
||||
demo.dbuf->maxsize = MAXSIZE + demo.dbuf->bufsize;
|
||||
demo.dbuf->sz.maxsize = MAXSIZE + demo.dbuf->bufsize;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -584,55 +580,6 @@ memwrite (QFile * _mem, const void *buffer, int size)
|
|||
return size;
|
||||
}
|
||||
|
||||
static char chartbl[256];
|
||||
void CleanName_Init ();
|
||||
|
||||
void
|
||||
Demo_Init (void)
|
||||
{
|
||||
int p, size = MIN_DEMO_MEMORY;
|
||||
|
||||
p = COM_CheckParm ("-democache");
|
||||
if (p) {
|
||||
if (p < com_argc - 1)
|
||||
size = atoi (com_argv[p + 1]) * 1024;
|
||||
else
|
||||
Sys_Error ("Memory_Init: you must specify a size in KB after "
|
||||
"-democache");
|
||||
}
|
||||
|
||||
if (size < MIN_DEMO_MEMORY) {
|
||||
Con_Printf ("Minimum memory size for demo cache is %dk\n",
|
||||
MIN_DEMO_MEMORY / 1024);
|
||||
size = MIN_DEMO_MEMORY;
|
||||
}
|
||||
|
||||
demo.name = dstring_newstr ();
|
||||
demo.path = dstring_newstr ();
|
||||
|
||||
svs.demomem = Hunk_AllocName (size, "demo");
|
||||
svs.demomemsize = size;
|
||||
demo_max_size = size - 0x80000;
|
||||
CleanName_Init ();
|
||||
|
||||
serverdemo = Cvar_Get ("serverdemo", "", CVAR_SERVERINFO, Cvar_Info, "");
|
||||
sv_demofps = Cvar_Get ("sv_demofps", "20", CVAR_NONE, 0, "");
|
||||
sv_demoPings = Cvar_Get ("sv_demoPings", "3", CVAR_NONE, 0, "");
|
||||
sv_demoNoVis = Cvar_Get ("sv_demoNoVis", "1", CVAR_NONE, 0, "");
|
||||
sv_demoUseCache = Cvar_Get ("sv_demoUseCache", "0", CVAR_NONE, 0, "");
|
||||
sv_demoCacheSize = Cvar_Get ("sv_demoCacheSize", va ("%d", size / 1024),
|
||||
CVAR_ROM, 0, "");
|
||||
sv_demoMaxSize = Cvar_Get ("sv_demoMaxSize", "20480", CVAR_NONE, 0, "");
|
||||
sv_demoMaxDirSize = Cvar_Get ("sv_demoMaxDirSize", "102400", CVAR_NONE, 0,
|
||||
"");
|
||||
sv_demoDir = Cvar_Get ("sv_demoDir", "demos", CVAR_NONE, 0, "");
|
||||
sv_demoPrefix = Cvar_Get ("sv_demoPrefix", "", CVAR_NONE, 0, "");
|
||||
sv_demoSuffix = Cvar_Get ("sv_demoSuffix", "", CVAR_NONE, 0, "");
|
||||
sv_onrecordfinish = Cvar_Get ("sv_onrecordfinish", "", CVAR_NONE, 0, "");
|
||||
sv_ondemoremove = Cvar_Get ("sv_ondemoremove", "", CVAR_NONE, 0, "");
|
||||
sv_demotxt = Cvar_Get ("sv_demotxt", "1", CVAR_NONE, 0, "");
|
||||
}
|
||||
|
||||
qboolean
|
||||
SV_InitRecord (void)
|
||||
{
|
||||
|
@ -690,7 +637,7 @@ SV_Stop (int reason)
|
|||
// write a disconnect message to the demo file
|
||||
|
||||
// clearup to be sure message will fit
|
||||
demo.dbuf->cursize = 0;
|
||||
demo.dbuf->sz.cursize = 0;
|
||||
demo.dbuf->h = NULL;
|
||||
demo.dbuf->bufsize = 0;
|
||||
DemoWrite_Begin (dem_all, 0, 2 + strlen ("EndOfDemo"));
|
||||
|
@ -824,7 +771,6 @@ SV_PrintTeams (void)
|
|||
int i, j, numcl = 0, numt = 0;
|
||||
client_t *clients[MAX_CLIENTS];
|
||||
char buf[2048] = { 0 };
|
||||
extern char chartbl2[];
|
||||
|
||||
// count teams and players
|
||||
for (i = 0; i < MAX_CLIENTS; i++) {
|
||||
|
@ -866,7 +812,7 @@ SV_PrintTeams (void)
|
|||
if (!numcl)
|
||||
return "\n";
|
||||
for (p = buf; *p; p++)
|
||||
*p = chartbl2[(byte) * p];
|
||||
*p = sys_char_map[(byte) * p];
|
||||
return va ("%s", buf);
|
||||
}
|
||||
|
||||
|
@ -884,16 +830,17 @@ SV_Record (char *name)
|
|||
int n, i;
|
||||
char path[MAX_OSPATH];
|
||||
char *info;
|
||||
dstring_t *tn = demo.name, *tp = demo.path;
|
||||
|
||||
client_t *player;
|
||||
const char *gamedir, *s;
|
||||
int seq = 1;
|
||||
|
||||
memset (&demo, 0, sizeof (demo));
|
||||
/*XXX
|
||||
for (i = 0; i < UPDATE_BACKUP; i++)
|
||||
demo.recorder.frames[i].entities.entities = demo_entities[i];
|
||||
*/
|
||||
dstring_clearstr (demo.name = tn);
|
||||
dstring_clearstr (demo.path = tp);
|
||||
|
||||
DemoBuffer_Init (&demo.dbuffer, demo.buffer, sizeof (demo.buffer));
|
||||
DemoSetMsgBuf (NULL, &demo.frames[0].buf);
|
||||
|
@ -1127,87 +1074,6 @@ SV_Record (char *name)
|
|||
// done
|
||||
}
|
||||
|
||||
/*
|
||||
SV_CleanName_Init
|
||||
|
||||
sets chararcter table for quake text->filename translation
|
||||
*/
|
||||
|
||||
void
|
||||
CleanName_Init ()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
chartbl[i] = (((i & 127) < 'a' || (i & 127) > 'z')
|
||||
&& ((i & 127) < '0'
|
||||
|| (i & 127) > '9')) ? '_' : (i & 127);
|
||||
|
||||
// special cases
|
||||
|
||||
// numbers
|
||||
for (i = 18; i < 29; i++)
|
||||
chartbl[i] = chartbl[i + 128] = i + 30;
|
||||
|
||||
// allow lowercase only
|
||||
for (i = 'A'; i <= 'Z'; i++)
|
||||
chartbl[i] = chartbl[i + 128] = i + 'a' - 'A';
|
||||
|
||||
// brackets
|
||||
chartbl[29] = chartbl[29 + 128] = chartbl[128] = '(';
|
||||
chartbl[31] = chartbl[31 + 128] = chartbl[130] = ')';
|
||||
chartbl[16] = chartbl[16 + 128] = '[';
|
||||
chartbl[17] = chartbl[17 + 128] = ']';
|
||||
|
||||
// dot
|
||||
chartbl[5] = chartbl[14] = chartbl[15] = chartbl[28] = chartbl[46] = '.';
|
||||
chartbl[5 + 128] = chartbl[14 + 128] = chartbl[15 + 128] =
|
||||
chartbl[28 + 128] = chartbl[46 + 128] = '.';
|
||||
|
||||
// !
|
||||
chartbl[33] = chartbl[33 + 128] = '!';
|
||||
|
||||
// #
|
||||
chartbl[35] = chartbl[35 + 128] = '#';
|
||||
|
||||
// %
|
||||
chartbl[37] = chartbl[37 + 128] = '%';
|
||||
|
||||
// &
|
||||
chartbl[38] = chartbl[38 + 128] = '&';
|
||||
|
||||
// '
|
||||
chartbl[39] = chartbl[39 + 128] = '\'';
|
||||
|
||||
// (
|
||||
chartbl[40] = chartbl[40 + 128] = '(';
|
||||
|
||||
// )
|
||||
chartbl[41] = chartbl[41 + 128] = ')';
|
||||
|
||||
// +
|
||||
chartbl[43] = chartbl[43 + 128] = '+';
|
||||
|
||||
// -
|
||||
chartbl[45] = chartbl[45 + 128] = '-';
|
||||
|
||||
// @
|
||||
chartbl[64] = chartbl[64 + 128] = '@';
|
||||
|
||||
// ^
|
||||
chartbl[94] = chartbl[94 + 128] = '^';
|
||||
|
||||
|
||||
chartbl[91] = chartbl[91 + 128] = '[';
|
||||
chartbl[93] = chartbl[93 + 128] = ']';
|
||||
|
||||
chartbl[16] = chartbl[16 + 128] = '[';
|
||||
chartbl[17] = chartbl[17 + 128] = ']';
|
||||
|
||||
chartbl[123] = chartbl[123 + 128] = '{';
|
||||
chartbl[125] = chartbl[125 + 128] = '}';
|
||||
}
|
||||
|
||||
/*
|
||||
SV_CleanName
|
||||
|
||||
|
@ -1220,13 +1086,13 @@ SV_CleanName (const unsigned char *name)
|
|||
static char text[1024];
|
||||
char *out = text;
|
||||
|
||||
*out = chartbl[*name++];
|
||||
*out = sys_char_map[*name++];
|
||||
|
||||
while (*name)
|
||||
if (*out == '_' && chartbl[*name] == '_')
|
||||
if (*out == '_' && sys_char_map[*name] == '_')
|
||||
name++;
|
||||
else
|
||||
*++out = chartbl[*name++];
|
||||
*++out = sys_char_map[*name++];
|
||||
|
||||
*++out = 0;
|
||||
return text;
|
||||
|
@ -1766,3 +1632,61 @@ SV_DemoInfo_f (void)
|
|||
|
||||
Qclose (f);
|
||||
}
|
||||
|
||||
void
|
||||
Demo_Init (void)
|
||||
{
|
||||
int p, size = MIN_DEMO_MEMORY;
|
||||
|
||||
p = COM_CheckParm ("-democache");
|
||||
if (p) {
|
||||
if (p < com_argc - 1)
|
||||
size = atoi (com_argv[p + 1]) * 1024;
|
||||
else
|
||||
Sys_Error ("Memory_Init: you must specify a size in KB after "
|
||||
"-democache");
|
||||
}
|
||||
|
||||
if (size < MIN_DEMO_MEMORY) {
|
||||
Con_Printf ("Minimum memory size for demo cache is %dk\n",
|
||||
MIN_DEMO_MEMORY / 1024);
|
||||
size = MIN_DEMO_MEMORY;
|
||||
}
|
||||
|
||||
demo.name = dstring_newstr ();
|
||||
demo.path = dstring_newstr ();
|
||||
|
||||
svs.demomem = Hunk_AllocName (size, "demo");
|
||||
svs.demomemsize = size;
|
||||
demo_max_size = size - 0x80000;
|
||||
|
||||
serverdemo = Cvar_Get ("serverdemo", "", CVAR_SERVERINFO, Cvar_Info,
|
||||
"FIXME");
|
||||
sv_demofps = Cvar_Get ("sv_demofps", "20", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoPings = Cvar_Get ("sv_demoPings", "3", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoNoVis = Cvar_Get ("sv_demoNoVis", "1", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoUseCache = Cvar_Get ("sv_demoUseCache", "0", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoCacheSize = Cvar_Get ("sv_demoCacheSize", va ("%d", size / 1024),
|
||||
CVAR_ROM, 0, "FIXME");
|
||||
sv_demoMaxSize = Cvar_Get ("sv_demoMaxSize", "20480", CVAR_NONE, 0,
|
||||
"FIXME");
|
||||
sv_demoMaxDirSize = Cvar_Get ("sv_demoMaxDirSize", "102400", CVAR_NONE, 0,
|
||||
"FIXME");
|
||||
sv_demoDir = Cvar_Get ("sv_demoDir", "demos", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoPrefix = Cvar_Get ("sv_demoPrefix", "", CVAR_NONE, 0, "FIXME");
|
||||
sv_demoSuffix = Cvar_Get ("sv_demoSuffix", "", CVAR_NONE, 0, "FIXME");
|
||||
sv_onrecordfinish = Cvar_Get ("sv_onrecordfinish", "", CVAR_NONE, 0, "FIXME");
|
||||
sv_ondemoremove = Cvar_Get ("sv_ondemoremove", "", CVAR_NONE, 0, "FIXME");
|
||||
sv_demotxt = Cvar_Get ("sv_demotxt", "1", CVAR_NONE, 0, "FIXME");
|
||||
|
||||
Cmd_AddCommand ("record", SV_Record_f, "FIXME");
|
||||
Cmd_AddCommand ("easyrecord", SV_EasyRecord_f, "FIXME");
|
||||
Cmd_AddCommand ("stop", SV_Stop_f, "FIXME");
|
||||
Cmd_AddCommand ("cancel", SV_Cancel_f, "FIXME");
|
||||
Cmd_AddCommand ("demolist", SV_DemoList_f, "FIXME");
|
||||
Cmd_AddCommand ("rmdemo", SV_DemoRemove_f, "FIXME");
|
||||
Cmd_AddCommand ("rmdemonum", SV_DemoRemoveNum_f, "FIXME");
|
||||
Cmd_AddCommand ("demoInfoAdd", SV_DemoInfoAdd_f, "FIXME");
|
||||
Cmd_AddCommand ("demoInfoRemove", SV_DemoInfoRemove_f, "FIXME");
|
||||
Cmd_AddCommand ("demoInfo", SV_DemoInfo_f, "FIXME");
|
||||
}
|
||||
|
|
|
@ -37,12 +37,14 @@ static const char rcsid[] =
|
|||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "msg_ucmd.h"
|
||||
#include "server.h"
|
||||
#include "sv_demo.h"
|
||||
#include "sv_progs.h"
|
||||
|
||||
|
||||
|
@ -108,6 +110,7 @@ SV_FatPVS (vec3_t org)
|
|||
#define MAX_NAILS 32
|
||||
edict_t *nails[MAX_NAILS];
|
||||
int numnails;
|
||||
int nailcount;
|
||||
|
||||
|
||||
qboolean
|
||||
|
@ -124,7 +127,7 @@ SV_AddNailUpdate (edict_t *ent)
|
|||
}
|
||||
|
||||
void
|
||||
SV_EmitNailUpdate (sizebuf_t *msg)
|
||||
SV_EmitNailUpdate (sizebuf_t *msg, qboolean recorder)
|
||||
{
|
||||
byte *buf; // [48 bits] xyzpy 12 12 12 4 8
|
||||
int n, p, x, y, z, yaw;
|
||||
|
@ -134,11 +137,20 @@ SV_EmitNailUpdate (sizebuf_t *msg)
|
|||
return;
|
||||
|
||||
buf = SZ_GetSpace (msg, numnails * 6 + 2);
|
||||
*buf++ = svc_nails;
|
||||
*buf++ = recorder ? svc_nails2 : svc_nails;
|
||||
*buf++ = numnails;
|
||||
|
||||
for (n = 0; n < numnails; n++) {
|
||||
ent = nails[n];
|
||||
if (recorder) {
|
||||
if (!SVfloat (ent, colormap)) {
|
||||
if (!((++nailcount) & 255))
|
||||
nailcount++;
|
||||
SVfloat (ent, colormap) = nailcount&255;
|
||||
}
|
||||
*buf++ = (byte)SVfloat (ent, colormap);
|
||||
}
|
||||
|
||||
x = ((int) (SVvector (ent, origin)[0] + 4096 + 1) >> 1) & 4095;
|
||||
y = ((int) (SVvector (ent, origin)[1] + 4096 + 1) >> 1) & 4095;
|
||||
z = ((int) (SVvector (ent, origin)[2] + 4096 + 1) >> 1) & 4095;
|
||||
|
@ -350,8 +362,16 @@ SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (newnum < oldnum) { // this is a new entity, send it from
|
||||
// the baseline
|
||||
if (newnum < oldnum) {
|
||||
// this is a new entity, send it from the baseline
|
||||
if (newnum == 9999) {
|
||||
Sys_Printf ("LOL, %d, %d, %d, %d %d %d\n", newnum, oldnum,
|
||||
to->num_entities, oldmax,
|
||||
client->netchan.incoming_sequence & UPDATE_MASK,
|
||||
client->delta_sequence & UPDATE_MASK);
|
||||
if (!client->edict)
|
||||
Sys_Printf("demo\n");
|
||||
}
|
||||
ent = EDICT_NUM (&sv_pr_state, newnum);
|
||||
// SV_Printf ("baseline %i\n", newnum);
|
||||
SV_WriteDelta (ent->data, &to->entities[newindex], msg, true,
|
||||
|
@ -372,6 +392,15 @@ SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
|
|||
MSG_WriteShort (msg, 0); // end of packetentities
|
||||
}
|
||||
|
||||
#define DF_ORIGIN 1 //FIXME move to protocol.h
|
||||
#define DF_ANGLES (1<<3)
|
||||
#define DF_EFFECTS (1<<6)
|
||||
#define DF_SKINNUM (1<<7)
|
||||
#define DF_DEAD (1<<8)
|
||||
#define DF_GIB (1<<9)
|
||||
#define DF_WEAPONFRAME (1<<10)
|
||||
#define DF_MODEL (1<<11)
|
||||
|
||||
void
|
||||
SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
|
||||
sizebuf_t *msg)
|
||||
|
@ -380,13 +409,54 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
|
|||
client_t *cl;
|
||||
edict_t *ent;
|
||||
usercmd_t cmd;
|
||||
demo_frame_t *demo_frame;
|
||||
demo_client_t *dcl;
|
||||
|
||||
demo_frame = &demo.frames[demo.parsecount & DEMO_FRAMES_MASK];
|
||||
|
||||
for (j = 0, cl = svs.clients, dcl = demo_frame->clients; j < MAX_CLIENTS;
|
||||
j++, cl++, dcl++) {
|
||||
|
||||
for (j = 0, cl = svs.clients; j < MAX_CLIENTS; j++, cl++) {
|
||||
if (cl->state != cs_spawned)
|
||||
continue;
|
||||
|
||||
ent = cl->edict;
|
||||
|
||||
if (!clent) {
|
||||
if (cl->spectator)
|
||||
continue;
|
||||
|
||||
dcl->parsecount = demo.parsecount;
|
||||
VectorCopy (SVvector (ent, origin), dcl->info.origin);
|
||||
VectorCopy (SVvector (ent, angles), dcl->info.angles);
|
||||
dcl->info.angles[0] *= -3;
|
||||
dcl->info.angles[2] = 0; // no roll angle
|
||||
|
||||
if (SVfloat (ent, health) <= 0) {
|
||||
// don't show the corpse looking around...
|
||||
dcl->info.angles[0] = 0;
|
||||
dcl->info.angles[1] = SVvector (ent, angles)[1];
|
||||
dcl->info.angles[2] = 0;
|
||||
}
|
||||
|
||||
dcl->info.skinnum = SVfloat (ent, skin);
|
||||
dcl->info.effects = SVfloat (ent, effects);
|
||||
dcl->info.weaponframe = SVfloat (ent, weaponframe);
|
||||
dcl->info.model = SVfloat (ent, modelindex);
|
||||
dcl->sec = sv.time - cl->localtime;
|
||||
dcl->frame = SVfloat (ent, frame);
|
||||
dcl->flags = 0;
|
||||
dcl->cmdtime = cl->localtime;
|
||||
dcl->fixangle = demo.fixangle[j];
|
||||
demo.fixangle[j] = 0;
|
||||
|
||||
if (SVfloat (ent, health) <= 0)
|
||||
dcl->flags |= DF_DEAD;
|
||||
if (SVvector (ent, mins)[2] != -24)
|
||||
dcl->flags |= DF_GIB;
|
||||
continue;
|
||||
}
|
||||
|
||||
// ZOID visibility tracking
|
||||
if (ent != clent &&
|
||||
!(client->spec_track && client->spec_track - 1 == j)) {
|
||||
|
@ -438,11 +508,11 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
|
|||
pflags |= PF_QF;
|
||||
}
|
||||
|
||||
if (cl->spectator) { // only sent origin and velocity to
|
||||
// spectators
|
||||
if (cl->spectator) {
|
||||
// only sent origin and velocity to spectators
|
||||
pflags &= PF_VELOCITY1 | PF_VELOCITY2 | PF_VELOCITY3;
|
||||
} else if (ent == clent) { // don't send a lot of data on
|
||||
// personal entity
|
||||
} else if (ent == clent) {
|
||||
// don't send a lot of data on personal entity
|
||||
pflags &= ~(PF_MSEC | PF_COMMAND);
|
||||
if (SVfloat (ent, weaponframe))
|
||||
pflags |= PF_WEAPONFRAME;
|
||||
|
@ -540,7 +610,7 @@ SV_WritePlayersToClient (client_t *client, edict_t *clent, byte * pvs,
|
|||
svc_playerinfo messages
|
||||
*/
|
||||
void
|
||||
SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
|
||||
SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean recorder)
|
||||
{
|
||||
byte *pvs;
|
||||
int e, i, num_edicts, mpe_moaned = 0;
|
||||
|
@ -555,8 +625,29 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
|
|||
|
||||
// find the client's PVS
|
||||
clent = client->edict;
|
||||
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
|
||||
pvs = SV_FatPVS (org);
|
||||
pvs = 0;
|
||||
if (!recorder) {
|
||||
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
|
||||
pvs = SV_FatPVS (org);
|
||||
} else {
|
||||
client_t *cl;
|
||||
|
||||
for (i=0, cl = svs.clients; i<MAX_CLIENTS; i++, cl++) {
|
||||
if (cl->state != cs_spawned)
|
||||
continue;
|
||||
|
||||
if (cl->spectator)
|
||||
continue;
|
||||
|
||||
VectorAdd (SVvector (cl->edict, origin),
|
||||
SVvector (cl->edict, view_ofs), org);
|
||||
if (pvs == NULL) {
|
||||
pvs = SV_FatPVS (org);
|
||||
} else {
|
||||
SV_AddToFatPVS (org, sv.worldmodel->nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send over the players in the PVS
|
||||
SV_WritePlayersToClient (client, clent, pvs, msg);
|
||||
|
@ -580,13 +671,15 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
|
|||
|| !*PR_GetString (&sv_pr_state, SVstring (ent, model)))
|
||||
continue;
|
||||
|
||||
// ignore if not touching a PV leaf
|
||||
for (i = 0; i < ent->num_leafs; i++)
|
||||
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7)))
|
||||
break;
|
||||
if (!sv_demoNoVis->int_val || !recorder) {
|
||||
// ignore if not touching a PV leaf
|
||||
for (i = 0; i < ent->num_leafs; i++)
|
||||
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7)))
|
||||
break;
|
||||
|
||||
if (i == ent->num_leafs)
|
||||
continue; // not visible
|
||||
if (i == ent->num_leafs)
|
||||
continue; // not visible
|
||||
}
|
||||
|
||||
if (SV_AddNailUpdate (ent))
|
||||
continue; // added to the special update list
|
||||
|
@ -654,5 +747,5 @@ SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg)
|
|||
SV_EmitPacketEntities (client, pack, msg);
|
||||
|
||||
// now add the specialized nail update
|
||||
SV_EmitNailUpdate (msg);
|
||||
SV_EmitNailUpdate (msg, recorder);
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ static const char rcsid[] =
|
|||
#include "net.h"
|
||||
#include "pmove.h"
|
||||
#include "server.h"
|
||||
#include "sv_demo.h"
|
||||
#include "sv_progs.h"
|
||||
|
||||
SERVER_PLUGIN_PROTOS
|
||||
|
@ -99,6 +100,7 @@ cbuf_args_t *sv_args;
|
|||
|
||||
client_t *host_client; // current client
|
||||
client_static_t cls; //FIXME needed by netchan :/
|
||||
entity_state_t cl_entities[MAX_CLIENTS][UPDATE_BACKUP+1][MAX_PACKET_ENTITIES]; // client entities
|
||||
|
||||
double sv_frametime;
|
||||
double realtime; // without any filtering or bounding
|
||||
|
@ -153,6 +155,7 @@ cvar_t *allow_download_skins;
|
|||
cvar_t *allow_download_models;
|
||||
cvar_t *allow_download_sounds;
|
||||
cvar_t *allow_download_maps;
|
||||
cvar_t *allow_download_demos;
|
||||
|
||||
cvar_t *sv_highchars;
|
||||
cvar_t *sv_phs;
|
||||
|
@ -230,6 +233,9 @@ SV_Shutdown (void)
|
|||
Qclose (sv_fraglogfile);
|
||||
sv_fraglogfile = NULL;
|
||||
}
|
||||
if (sv.demorecording)
|
||||
SV_Stop_f();
|
||||
|
||||
NET_Shutdown ();
|
||||
Con_Shutdown ();
|
||||
}
|
||||
|
@ -871,6 +877,11 @@ SVC_DirectConnect (void)
|
|||
// accept the new client
|
||||
// this is the only place a client_t is ever initialized
|
||||
*newcl = temp;
|
||||
for (i = 0; i < UPDATE_BACKUP; i++) {
|
||||
newcl->frames[i].entities.entities = cl_entities[newcl-svs.clients][i];
|
||||
memset (cl_entities[newcl-svs.clients][i], 0,
|
||||
sizeof (cl_entities[newcl-svs.clients][i]));
|
||||
}
|
||||
|
||||
Netchan_OutOfBandPrint (adr, "%c", S2C_CONNECTION);
|
||||
|
||||
|
@ -1859,6 +1870,7 @@ void
|
|||
SV_Frame (float time)
|
||||
{
|
||||
static double start, end;
|
||||
double demo_start, demo_end;
|
||||
|
||||
start = Sys_DoubleTime ();
|
||||
svs.stats.idle += start - end;
|
||||
|
@ -1919,6 +1931,11 @@ SV_Frame (float time)
|
|||
// send messages back to the clients that had packets read this frame
|
||||
SV_SendClientMessages ();
|
||||
|
||||
demo_start = Sys_DoubleTime ();
|
||||
SV_SendDemoMessage ();
|
||||
demo_end = Sys_DoubleTime ();
|
||||
svs.stats.demo += demo_end - demo_start;
|
||||
|
||||
// send a heartbeat to the master if needed
|
||||
Master_Heartbeat ();
|
||||
|
||||
|
@ -1931,10 +1948,12 @@ SV_Frame (float time)
|
|||
svs.stats.latched_active = svs.stats.active;
|
||||
svs.stats.latched_idle = svs.stats.idle;
|
||||
svs.stats.latched_packets = svs.stats.packets;
|
||||
svs.stats.latched_demo = svs.stats.demo;
|
||||
svs.stats.active = 0;
|
||||
svs.stats.idle = 0;
|
||||
svs.stats.packets = 0;
|
||||
svs.stats.count = 0;
|
||||
svs.stats.demo = 0;
|
||||
}
|
||||
Con_ProcessInput (); //XXX evil hack to get the cursor in the right place
|
||||
}
|
||||
|
@ -2082,6 +2101,9 @@ SV_InitLocal (void)
|
|||
allow_download_maps = Cvar_Get ("allow_download_maps", "1", CVAR_NONE,
|
||||
NULL, "Toggle if clients can download "
|
||||
"maps from the server");
|
||||
allow_download_demos = Cvar_Get ("allow_download_demos", "1", CVAR_NONE,
|
||||
NULL, "Toggle if clients can download "
|
||||
"maps from the server");
|
||||
sv_highchars = Cvar_Get ("sv_highchars", "1", CVAR_NONE, NULL,
|
||||
"Toggle the use of high character color names "
|
||||
"for players");
|
||||
|
@ -2283,7 +2305,7 @@ SV_ExtractFromUserinfo (client_t *cl)
|
|||
if (strcmp (val, newname)) {
|
||||
Netchan_OutOfBandPrint (net_from, "%c\nPlease choose a "
|
||||
"different name.\n", A2C_PRINT);
|
||||
SV_ClientPrintf (cl, PRINT_HIGH, "Please choose a "
|
||||
SV_ClientPrintf (1, cl, PRINT_HIGH, "Please choose a "
|
||||
"different name.\n");
|
||||
SV_Printf("Client %d kicked for having a invalid name\n",
|
||||
cl->userid);
|
||||
|
@ -2299,7 +2321,7 @@ SV_ExtractFromUserinfo (client_t *cl)
|
|||
} else if (cl->lastnamecount++ > 4) {
|
||||
SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked for "
|
||||
"name spam\n", cl->name);
|
||||
SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked "
|
||||
SV_ClientPrintf (1, cl, PRINT_HIGH, "You were kicked "
|
||||
"from the game for name spamming\n");
|
||||
cl->drop = true;
|
||||
return;
|
||||
|
@ -2485,6 +2507,8 @@ SV_Init (void)
|
|||
SV_InitLocal ();
|
||||
Pmove_Init ();
|
||||
|
||||
Demo_Init ();
|
||||
|
||||
Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
|
||||
host_hunklevel = Hunk_LowMark ();
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ PF_sprint (progs_t *pr)
|
|||
|
||||
client = &svs.clients[entnum - 1];
|
||||
|
||||
SV_ClientPrintf (client, level, "%s", s);
|
||||
SV_ClientPrintf (1, client, level, "%s", s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,6 +50,7 @@ static const char rcsid[] =
|
|||
#include "bothdefs.h"
|
||||
#include "compat.h"
|
||||
#include "server.h"
|
||||
#include "sv_demo.h"
|
||||
#include "sv_progs.h"
|
||||
|
||||
#define CHAN_AUTO 0
|
||||
|
@ -248,7 +249,7 @@ SV_PrintToClient (client_t *cl, int level, const char *string)
|
|||
Sends text across to be displayed if the level passes
|
||||
*/
|
||||
void
|
||||
SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...)
|
||||
SV_ClientPrintf (int recorder, client_t *cl, int level, const char *fmt, ...)
|
||||
{
|
||||
char string[1024];
|
||||
va_list argptr;
|
||||
|
@ -260,6 +261,13 @@ SV_ClientPrintf (client_t *cl, int level, const char *fmt, ...)
|
|||
vsnprintf (string, sizeof (string), fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (recorder && sv.demorecording) {
|
||||
DemoWrite_Begin (dem_single, cl - svs.clients, strlen (string) + 3);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, level);
|
||||
MSG_WriteString (&demo.dbuf->sz, string);
|
||||
}
|
||||
|
||||
SV_PrintToClient (cl, level, string);
|
||||
}
|
||||
|
||||
|
@ -290,6 +298,13 @@ SV_BroadcastPrintf (int level, const char *fmt, ...)
|
|||
|
||||
SV_PrintToClient (cl, level, string);
|
||||
}
|
||||
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin (dem_all, cl - svs.clients, strlen (string) + 3);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, level);
|
||||
MSG_WriteString (&demo.dbuf->sz, string);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -398,6 +413,15 @@ SV_Multicast (const vec3_t origin, int to)
|
|||
sv.multicast.cursize);
|
||||
}
|
||||
|
||||
if (sv.demorecording) {
|
||||
if (reliable) {
|
||||
//DemoWrite_Begin(dem_multiple, cls, sv.multicast.cursize);
|
||||
DemoWrite_Begin(dem_all, 0, sv.multicast.cursize);
|
||||
SZ_Write (&demo.dbuf->sz, sv.multicast.data, sv.multicast.cursize);
|
||||
} else
|
||||
SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize);
|
||||
}
|
||||
|
||||
SZ_Clear (&sv.multicast);
|
||||
}
|
||||
|
||||
|
@ -518,10 +542,12 @@ void
|
|||
SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
|
||||
{
|
||||
edict_t *ent, *other;
|
||||
int i;
|
||||
int i, clnum;
|
||||
|
||||
ent = client->edict;
|
||||
|
||||
clnum = NUM_FOR_EDICT (&sv_pr_state, ent) - 1;
|
||||
|
||||
// send the chokecount for r_netgraph
|
||||
if (client->chokecount) {
|
||||
MSG_WriteByte (msg, svc_chokecount);
|
||||
|
@ -541,11 +567,26 @@ SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
|
|||
SVfloat (ent, dmg_take) = 0;
|
||||
SVfloat (ent, dmg_save) = 0;
|
||||
}
|
||||
|
||||
// add this to server demo
|
||||
if (sv.demorecording && msg->cursize) {
|
||||
DemoWrite_Begin(dem_single, clnum, msg->cursize);
|
||||
SZ_Write(&demo.dbuf->sz, msg->data, msg->cursize);
|
||||
}
|
||||
|
||||
// a fixangle might get lost in a dropped packet. Oh well.
|
||||
if (SVfloat (ent, fixangle)) {
|
||||
MSG_WriteByte (msg, svc_setangle);
|
||||
MSG_WriteAngleV (msg, SVvector (ent, angles));
|
||||
VectorCopy (SVvector (ent, angles), demo.angles[clnum]);
|
||||
SVfloat (ent, fixangle) = 0;
|
||||
demo.fixangle[clnum] = true;
|
||||
|
||||
if (sv.demorecording) {
|
||||
MSG_WriteByte (&demo.datagram, svc_setangle);
|
||||
MSG_WriteByte (&demo.datagram, clnum);
|
||||
MSG_WriteAngleV (&demo.datagram, demo.angles[clnum]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,7 +669,7 @@ SV_SendClientDatagram (client_t *client)
|
|||
// send over all the objects that are in the PVS
|
||||
// this will include clients, a packetentities, and
|
||||
// possibly a nails update
|
||||
SV_WriteEntitiesToClient (client, &msg);
|
||||
SV_WriteEntitiesToClient (client, &msg, false);
|
||||
|
||||
// copy the accumulated multicast datagram
|
||||
// for this client out to the message
|
||||
|
@ -677,6 +718,14 @@ SV_UpdateToReliableMessages (void)
|
|||
frags));
|
||||
}
|
||||
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin(dem_all, 0, 4);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_updatefrags);
|
||||
MSG_WriteByte (&demo.dbuf->sz, i);
|
||||
MSG_WriteShort (&demo.dbuf->sz,
|
||||
SVfloat (host_client->edict, frags));
|
||||
}
|
||||
|
||||
host_client->old_frags = SVfloat (host_client->edict, frags);
|
||||
}
|
||||
// maxspeed/entgravity changes
|
||||
|
@ -687,12 +736,22 @@ SV_UpdateToReliableMessages (void)
|
|||
host_client->entgravity = SVfloat (ent, gravity);
|
||||
ClientReliableWrite_Begin (host_client, svc_entgravity, 5);
|
||||
ClientReliableWrite_Float (host_client, host_client->entgravity);
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin (dem_single, i, 5);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_entgravity);
|
||||
MSG_WriteFloat (&demo.dbuf->sz, host_client->entgravity);
|
||||
}
|
||||
}
|
||||
if (sv_fields.maxspeed != -1
|
||||
&& host_client->maxspeed != SVfloat (ent, maxspeed)) {
|
||||
host_client->maxspeed = SVfloat (ent, maxspeed);
|
||||
ClientReliableWrite_Begin (host_client, svc_maxspeed, 5);
|
||||
ClientReliableWrite_Float (host_client, host_client->maxspeed);
|
||||
if (sv.demorecording) {
|
||||
DemoWrite_Begin (dem_single, i, 5);
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_maxspeed);
|
||||
MSG_WriteFloat (&demo.dbuf->sz, host_client->maxspeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -702,8 +761,7 @@ SV_UpdateToReliableMessages (void)
|
|||
// append the broadcast messages to each client messages
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) {
|
||||
if (client->state < cs_connected)
|
||||
continue; // reliables go to all connected or
|
||||
// spawned
|
||||
continue; // reliables go to all connected or spawned
|
||||
|
||||
ClientReliableCheckBlock (client, sv.reliable_datagram.cursize);
|
||||
ClientReliableWrite_SZ (client, sv.reliable_datagram.data,
|
||||
|
@ -714,6 +772,14 @@ SV_UpdateToReliableMessages (void)
|
|||
SZ_Write (&client->datagram, sv.datagram.data, sv.datagram.cursize);
|
||||
}
|
||||
|
||||
if (sv.demorecording && sv.reliable_datagram.cursize) {
|
||||
DemoWrite_Begin (dem_all, 0, sv.reliable_datagram.cursize);
|
||||
SZ_Write (&demo.dbuf->sz, sv.reliable_datagram.data,
|
||||
sv.reliable_datagram.cursize);
|
||||
}
|
||||
if (sv.demorecording)
|
||||
SZ_Write(&demo.datagram, sv.datagram.data, sv.datagram.cursize); // FIXME: ???
|
||||
|
||||
SZ_Clear (&sv.reliable_datagram);
|
||||
SZ_Clear (&sv.datagram);
|
||||
}
|
||||
|
@ -814,6 +880,133 @@ SV_SendClientMessages (void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SV_SendDemoMessage(void)
|
||||
{
|
||||
int i, j, cls = 0;
|
||||
client_t *c;
|
||||
byte buf[MAX_DATAGRAM];
|
||||
sizebuf_t msg;
|
||||
edict_t *ent;
|
||||
int stats[MAX_CL_STATS];
|
||||
float min_fps;
|
||||
|
||||
if (!sv.demorecording)
|
||||
return;
|
||||
|
||||
if (sv_demoPings->value) {
|
||||
if (sv.time - demo.pingtime > sv_demoPings->value) {
|
||||
SV_DemoPings ();
|
||||
demo.pingtime = sv.time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!sv_demofps->value)
|
||||
min_fps = 20.0;
|
||||
else
|
||||
min_fps = sv_demofps->value;
|
||||
|
||||
min_fps = max(4, min_fps);
|
||||
if (sv.time - demo.time < 1.0 / min_fps)
|
||||
return;
|
||||
|
||||
for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
|
||||
{
|
||||
if (c->state != cs_spawned)
|
||||
continue; // datagrams only go to spawned
|
||||
|
||||
cls |= 1 << i;
|
||||
}
|
||||
|
||||
if (!cls) {
|
||||
SZ_Clear (&demo.datagram);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.data = buf;
|
||||
msg.maxsize = sizeof(buf);
|
||||
msg.cursize = 0;
|
||||
msg.allowoverflow = true;
|
||||
msg.overflowed = false;
|
||||
|
||||
for (i=0, c = svs.clients; i < MAX_CLIENTS; i++, c++) {
|
||||
if (c->state != cs_spawned)
|
||||
continue; // datagrams only go to spawned
|
||||
|
||||
if (c->spectator)
|
||||
continue;
|
||||
|
||||
ent = c->edict;
|
||||
memset (stats, 0, sizeof(stats));
|
||||
|
||||
stats[STAT_HEALTH] = SVfloat (ent, health);
|
||||
stats[STAT_WEAPON] = SV_ModelIndex (PR_GetString (&sv_pr_state,
|
||||
SVstring (ent, weaponmodel)));
|
||||
stats[STAT_AMMO] = SVfloat (ent, currentammo);
|
||||
stats[STAT_ARMOR] = SVfloat (ent, armorvalue);
|
||||
stats[STAT_SHELLS] = SVfloat (ent, ammo_shells);
|
||||
stats[STAT_NAILS] = SVfloat (ent, ammo_nails);
|
||||
stats[STAT_ROCKETS] = SVfloat (ent, ammo_rockets);
|
||||
stats[STAT_CELLS] = SVfloat (ent, ammo_cells);
|
||||
stats[STAT_ACTIVEWEAPON] = SVfloat (ent, weapon);
|
||||
|
||||
|
||||
// stuff the sigil bits into the high bits of items for sbar
|
||||
stats[STAT_ITEMS] = ((int)SVfloat (ent, items)
|
||||
| ((int)sv_globals.serverflags << 28));
|
||||
|
||||
for (j=0 ; j<MAX_CL_STATS ; j++)
|
||||
if (stats[j] != demo.stats[i][j]) {
|
||||
demo.stats[i][j] = stats[j];
|
||||
if (stats[j] >=0 && stats[j] <= 255) {
|
||||
DemoWrite_Begin(dem_stats, i, 3);
|
||||
MSG_WriteByte(&demo.dbuf->sz, svc_updatestat);
|
||||
MSG_WriteByte(&demo.dbuf->sz, j);
|
||||
MSG_WriteByte(&demo.dbuf->sz, stats[j]);
|
||||
} else {
|
||||
DemoWrite_Begin(dem_stats, i, 6);
|
||||
MSG_WriteByte(&demo.dbuf->sz, svc_updatestatlong);
|
||||
MSG_WriteByte(&demo.dbuf->sz, j);
|
||||
MSG_WriteLong(&demo.dbuf->sz, stats[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send over all the objects that are in the PVS
|
||||
// this will include clients, a packetentities, and
|
||||
// possibly a nails update
|
||||
msg.cursize = 0;
|
||||
if (!demo.recorder.delta_sequence)
|
||||
demo.recorder.delta_sequence = -1;
|
||||
SV_WriteEntitiesToClient (&demo.recorder, &msg, true);
|
||||
DemoWrite_Begin(dem_all, 0, msg.cursize);
|
||||
SZ_Write (&demo.dbuf->sz, msg.data, msg.cursize);
|
||||
// copy the accumulated multicast datagram
|
||||
// for this client out to the message
|
||||
if (demo.datagram.cursize) {
|
||||
DemoWrite_Begin(dem_all, 0, demo.datagram.cursize);
|
||||
SZ_Write (&demo.dbuf->sz, demo.datagram.data, demo.datagram.cursize);
|
||||
SZ_Clear (&demo.datagram);
|
||||
}
|
||||
|
||||
demo.recorder.delta_sequence = demo.recorder.netchan.incoming_sequence&255;
|
||||
demo.recorder.netchan.incoming_sequence++;
|
||||
demo.frames[demo.parsecount&DEMO_FRAMES_MASK].time = demo.time = sv.time;
|
||||
|
||||
// that's a backup of 3sec in 20fps, should be enough
|
||||
if (demo.parsecount - demo.lastwritten > 60) {
|
||||
SV_DemoWritePackets(1);
|
||||
}
|
||||
|
||||
demo.parsecount++;
|
||||
DemoSetMsgBuf(demo.dbuf,
|
||||
&demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf);
|
||||
|
||||
if (sv_demoMaxSize->int_val && demo.size > sv_demoMaxSize->int_val*1024)
|
||||
SV_Stop (1);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__GNUC__)
|
||||
# pragma optimize( "", on )
|
||||
#endif
|
||||
|
@ -830,8 +1023,7 @@ SV_SendMessagesToAll (void)
|
|||
int i;
|
||||
|
||||
for (i = 0, c = svs.clients; i < MAX_CLIENTS; i++, c++)
|
||||
if (c->state) // FIXME: should this only send to
|
||||
// active?
|
||||
if (c->state) // FIXME: should this only send to active?
|
||||
c->send_message = true;
|
||||
|
||||
SV_SendClientMessages ();
|
||||
|
|
|
@ -60,6 +60,7 @@ static const char rcsid[] =
|
|||
#include "msg_ucmd.h"
|
||||
#include "pmove.h"
|
||||
#include "server.h"
|
||||
#include "sv_demo.h"
|
||||
#include "sv_progs.h"
|
||||
#include "world.h"
|
||||
|
||||
|
@ -293,7 +294,7 @@ SV_PreSpawn_f (ucmd_t *cmd)
|
|||
|
||||
if (sv_mapcheck->int_val && check != sv.worldmodel->checksum &&
|
||||
check != sv.worldmodel->checksum2) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Map model file does "
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Map model file does "
|
||||
"not match (%s), %i != %i/%i.\n"
|
||||
"You may need a new version of the map, or the "
|
||||
"proper install files.\n",
|
||||
|
@ -522,7 +523,7 @@ SV_Begin_f (ucmd_t *cmd)
|
|||
if (sv.paused) {
|
||||
ClientReliableWrite_Begin (host_client, svc_setpause, 2);
|
||||
ClientReliableWrite_Byte (host_client, sv.paused);
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Server is paused.\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Server is paused.\n");
|
||||
}
|
||||
#if 0
|
||||
// send a fixangle over the reliable channel to make sure it gets there
|
||||
|
@ -597,7 +598,7 @@ SV_NextUpload (void)
|
|||
int percent, size;
|
||||
|
||||
if (!*host_client->uploadfn) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Upload denied\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Upload denied\n");
|
||||
ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
|
||||
ClientReliableWrite_String (host_client, "stopul");
|
||||
|
||||
|
@ -752,7 +753,7 @@ SV_Say (qboolean team)
|
|||
char text[2048], t1[32];
|
||||
const char *t2;
|
||||
client_t *client;
|
||||
int tmp, j;
|
||||
int tmp, j, cls = 0;
|
||||
|
||||
if (Cmd_Argc () < 2)
|
||||
return;
|
||||
|
@ -772,7 +773,7 @@ SV_Say (qboolean team)
|
|||
|
||||
if (fp_messages) {
|
||||
if (!sv.paused && realtime < host_client->lockedtill) {
|
||||
SV_ClientPrintf (host_client, PRINT_CHAT,
|
||||
SV_ClientPrintf (1, host_client, PRINT_CHAT,
|
||||
"You can't talk for %d more seconds\n",
|
||||
(int) (host_client->lockedtill - realtime));
|
||||
return;
|
||||
|
@ -784,10 +785,10 @@ SV_Say (qboolean team)
|
|||
&& (realtime - host_client->whensaid[tmp] < fp_persecond)) {
|
||||
host_client->lockedtill = realtime + fp_secondsdead;
|
||||
if (fp_msg[0])
|
||||
SV_ClientPrintf (host_client, PRINT_CHAT,
|
||||
SV_ClientPrintf (1, host_client, PRINT_CHAT,
|
||||
"FloodProt: %s\n", fp_msg);
|
||||
else
|
||||
SV_ClientPrintf (host_client, PRINT_CHAT,
|
||||
SV_ClientPrintf (1, host_client, PRINT_CHAT,
|
||||
"FloodProt: You can't talk for %d seconds.\n",
|
||||
fp_secondsdead);
|
||||
return;
|
||||
|
@ -812,7 +813,7 @@ SV_Say (qboolean team)
|
|||
SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked for "
|
||||
"attempting to fake messages\n",
|
||||
host_client->name);
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "You were kicked "
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "You were kicked "
|
||||
"for attempting to fake messages\n");
|
||||
SV_DropClient (host_client);
|
||||
return;
|
||||
|
@ -843,8 +844,23 @@ SV_Say (qboolean team)
|
|||
continue; // on different teams
|
||||
}
|
||||
}
|
||||
SV_ClientPrintf (client, PRINT_CHAT, "%s", text);
|
||||
cls |= 1 << j;
|
||||
SV_ClientPrintf (0, client, PRINT_CHAT, "%s", text);
|
||||
}
|
||||
|
||||
if (!sv.demorecording || !cls)
|
||||
return;
|
||||
// non-team messages should be seen allways, even if not tracking any
|
||||
// player
|
||||
if (!team && ((host_client->spectator && sv_spectalk->value)
|
||||
|| !host_client->spectator)) {
|
||||
DemoWrite_Begin (dem_all, 0, strlen (text) + 3);
|
||||
} else {
|
||||
DemoWrite_Begin (dem_multiple, cls, strlen (text) + 3);
|
||||
}
|
||||
MSG_WriteByte (&demo.dbuf->sz, svc_print);
|
||||
MSG_WriteByte (&demo.dbuf->sz, PRINT_CHAT);
|
||||
MSG_WriteString (&demo.dbuf->sz, text);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -891,7 +907,7 @@ SV_Kill_f (ucmd_t *cmd)
|
|||
{
|
||||
if (SVfloat (sv_player, health) <= 0) {
|
||||
SV_BeginRedirect (RD_CLIENT);
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH,
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH,
|
||||
"Can't suicide -- already dead!\n");
|
||||
SV_EndRedirect ();
|
||||
return;
|
||||
|
@ -932,7 +948,7 @@ SV_Pause_f (ucmd_t *cmd)
|
|||
currenttime = Sys_DoubleTime ();
|
||||
|
||||
if (lastpausetime + 1 > currenttime) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH,
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH,
|
||||
"Pause flood not allowed.\n");
|
||||
return;
|
||||
}
|
||||
|
@ -940,12 +956,12 @@ SV_Pause_f (ucmd_t *cmd)
|
|||
lastpausetime = currenttime;
|
||||
|
||||
if (!pausable->int_val) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Pause not allowed.\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Pause not allowed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (host_client->spectator) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH,
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH,
|
||||
"Spectators can not pause.\n");
|
||||
return;
|
||||
}
|
||||
|
@ -999,7 +1015,8 @@ SV_PTrack_f (ucmd_t *cmd)
|
|||
i = atoi (Cmd_Argv (1));
|
||||
if (i < 0 || i >= MAX_CLIENTS || svs.clients[i].state != cs_spawned ||
|
||||
svs.clients[i].spectator) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Invalid client to track\n");
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH,
|
||||
"Invalid client to track\n");
|
||||
host_client->spec_track = 0;
|
||||
ent = EDICT_NUM (&sv_pr_state, host_client - svs.clients + 1);
|
||||
tent = EDICT_NUM (&sv_pr_state, 0);
|
||||
|
@ -1024,7 +1041,7 @@ SV_Rate_f (ucmd_t *cmd)
|
|||
int rate;
|
||||
|
||||
if (Cmd_Argc () != 2) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Current rate is %i\n",
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Current rate is %i\n",
|
||||
(int) (1.0 / host_client->netchan.rate + 0.5));
|
||||
return;
|
||||
}
|
||||
|
@ -1036,7 +1053,7 @@ SV_Rate_f (ucmd_t *cmd)
|
|||
rate = max (500, rate);
|
||||
}
|
||||
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Net rate set to %i\n", rate);
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Net rate set to %i\n", rate);
|
||||
host_client->netchan.rate = 1.0 / rate;
|
||||
}
|
||||
|
||||
|
@ -1049,14 +1066,15 @@ void
|
|||
SV_Msg_f (ucmd_t *cmd)
|
||||
{
|
||||
if (Cmd_Argc () != 2) {
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Current msg level is %i\n",
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH,
|
||||
"Current msg level is %i\n",
|
||||
host_client->messagelevel);
|
||||
return;
|
||||
}
|
||||
|
||||
host_client->messagelevel = atoi (Cmd_Argv (1));
|
||||
|
||||
SV_ClientPrintf (host_client, PRINT_HIGH, "Msg level set to %i\n",
|
||||
SV_ClientPrintf (1, host_client, PRINT_HIGH, "Msg level set to %i\n",
|
||||
host_client->messagelevel);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue