From 8c051f3a96f700299c7df9208bcbcd92297b527a Mon Sep 17 00:00:00 2001 From: VVD Date: Mon, 18 Oct 2004 17:48:03 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r33, which included commits to RCS files with non-trunk default branches. --- make | 2 + make_sv | 2 + source/cl_demo.c | 1 - source/cl_ents.c | 1 - source/cl_main.c | 2 - source/cl_parse.c | 17 ++ source/common.c | 2 +- source/console.c | 6 +- source/keys.c | 16 +- source/net_chan.c | 2 +- source/pr_cmds.c | 57 ++++--- source/server.h | 25 ++- source/skin.c | 7 + source/sv_demo.c | 380 +++++++++++++++++++++++++++++++++++-------- source/sv_init.c | 6 +- source/sv_login.c | 91 +++++++---- source/sv_main.c | 192 +++++++++++++++++----- source/sv_sys_unix.c | 19 +-- source/sv_sys_win.c | 6 +- source/sv_user.c | 192 +++++++++++----------- source/version.h | 4 +- 21 files changed, 730 insertions(+), 300 deletions(-) create mode 100644 make create mode 100644 make_sv diff --git a/make b/make new file mode 100644 index 00000000..1eb7ef12 --- /dev/null +++ b/make @@ -0,0 +1,2 @@ +make build_sv + diff --git a/make_sv b/make_sv new file mode 100644 index 00000000..1eb7ef12 --- /dev/null +++ b/make_sv @@ -0,0 +1,2 @@ +make build_sv + diff --git a/source/cl_demo.c b/source/cl_demo.c index b361b39b..ec626b2a 100644 --- a/source/cl_demo.c +++ b/source/cl_demo.c @@ -208,7 +208,6 @@ qboolean CL_GetDemoMessage (void) { olddemotime = nextdemotime; if (cls.demoplayback2) { - Con_Printf("here\n"); cls.netchan.incoming_sequence++; cls.netchan.incoming_acknowledged++; cls.netchan.frame_latency = 0; diff --git a/source/cl_ents.c b/source/cl_ents.c index d41e1777..ef8b909d 100644 --- a/source/cl_ents.c +++ b/source/cl_ents.c @@ -833,7 +833,6 @@ void CL_ParsePlayerinfo (void) flags = MSG_ReadShort (); state->flags = TranslateFlags(flags); - Con_Printf("p:%d %d\n", cl.parsecount, num); state->messagenum = cl.parsecount; state->command.msec = 0; diff --git a/source/cl_main.c b/source/cl_main.c index b7611869..595be499 100644 --- a/source/cl_main.c +++ b/source/cl_main.c @@ -932,8 +932,6 @@ void Host_Frame (double time) { player_state_t *self, *oldself; - Con_Printf("%d, %d\n", cl.parsecount, cls.netchan.incoming_acknowledged); - self = &cl.frames[cl.parsecount & UPDATE_MASK].playerstate[cl.playernum]; oldself = &cl.frames[(cls.netchan.outgoing_sequence-1) & UPDATE_MASK].playerstate[cl.playernum]; self->messagenum = cl.parsecount; diff --git a/source/cl_parse.c b/source/cl_parse.c index f416e4af..440846ff 100644 --- a/source/cl_parse.c +++ b/source/cl_parse.c @@ -200,6 +200,13 @@ qboolean CL_CheckOrDownloadFile (char *filename) if (cls.demoplayback) return true; + if (cls.download) { + Con_Printf("here\n"); + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "nextdl"); + return false; + } + strcpy (cls.downloadname, filename); Con_Printf ("Downloading %s...\n", cls.downloadname); @@ -363,12 +370,22 @@ void CL_ParseDownload (void) int size, percent; byte name[1024]; int r; + static float time = 0; + static int s = 0; // read the data size = MSG_ReadShort (); percent = MSG_ReadByte (); + s += size; + if (realtime - time > 1) + { + cls.downloadrate = s/(1024*(realtime - time)); + time = realtime; + s = 0; + } + if (cls.demoplayback) { if (size > 0) msg_readcount += size; diff --git a/source/common.c b/source/common.c index 9e95b413..88dbad58 100644 --- a/source/common.c +++ b/source/common.c @@ -1443,7 +1443,7 @@ byte *COM_LoadFile (char *path, int usehunk) fread(buf+l, 1, 128, h); l += 128; if (l - count > READMAX && (sv_cpserver.value > 0) && (sv_cpserver.value < 100)) { - Sys_Sleep(sv_cpserver.value); + Sys_Sleep((unsigned long)sv_cpserver.value); count = l; } } diff --git a/source/console.c b/source/console.c index 80cea98f..9e84df18 100644 --- a/source/console.c +++ b/source/console.c @@ -623,10 +623,10 @@ void Con_DrawConsole (int lines) text = cls.downloadname; x = con_linewidth - ((con_linewidth * 7) / 40); - y = x - strlen(text) - 8; + y = x - strlen(text) - 10; i = con_linewidth/3; if (strlen(text) > i) { - y = x - i - 11; + y = x - i - 13; Q_strncpyz (dlbar, text, i+1); strcat(dlbar, "..."); } else @@ -648,7 +648,7 @@ void Con_DrawConsole (int lines) dlbar[i++] = '\x82'; dlbar[i] = 0; - sprintf(dlbar + strlen(dlbar), " %02d%%", cls.downloadpercent); + sprintf(dlbar + strlen(dlbar), " %02d%%(%dkb/s)", cls.downloadpercent, cls.downloadrate); // draw it y = con_vislines-22 + 8; diff --git a/source/keys.c b/source/keys.c index e5aa0251..9ac19eda 100644 --- a/source/keys.c +++ b/source/keys.c @@ -855,6 +855,7 @@ void Key_Event (int key, qboolean down) { char *kb; char cmd[1024]; + qboolean allow; // Con_Printf ("%i : %i\n", key, down); //@@@ @@ -920,10 +921,16 @@ void Key_Event (int key, qboolean down) // switch. Button commands include the kenum as a parameter, so multiple // downs can be matched with ups // + + allow = (key_dest == key_menu && menubound[key]) + || ((key_dest == key_console || key_dest == key_message) + && !consolekeys[key]) + || (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ); + if (!down) { kb = keybindings[key]; - if (kb && kb[0] == '+') + if (kb && kb[0] == '+' )//&& allow) { sprintf (cmd, "-%s %i\n", kb+1, key); Cbuf_AddText (cmd); @@ -931,7 +938,7 @@ void Key_Event (int key, qboolean down) if (keyshift[key] != key) { kb = keybindings[keyshift[key]]; - if (kb && kb[0] == '+') + if (kb && kb[0] == '+' )//&& allow) { sprintf (cmd, "-%s %i\n", kb+1, key); Cbuf_AddText (cmd); @@ -955,10 +962,7 @@ void Key_Event (int key, qboolean down) // // if not a consolekey, send to the interpreter no matter what mode is // - if ( (key_dest == key_menu && menubound[key]) - || ((key_dest == key_console || key_dest == key_message) - && !consolekeys[key]) - || (key_dest == key_game && ( cls.state == ca_active || !consolekeys[key] ) ) ) + if ( allow ) { kb = keybindings[key]; if (kb) diff --git a/source/net_chan.c b/source/net_chan.c index 2d284708..e99ea218 100644 --- a/source/net_chan.c +++ b/source/net_chan.c @@ -185,7 +185,7 @@ Netchan_CanPacket Returns true if the bandwidth choke isn't active ================ */ -#define MAX_BACKUP 200 +#define MAX_BACKUP 400 qboolean Netchan_CanPacket (netchan_t *chan) { if (chan->cleartime < realtime + MAX_BACKUP*chan->rate) diff --git a/source/pr_cmds.c b/source/pr_cmds.c index eae8dcea..3b9008d9 100644 --- a/source/pr_cmds.c +++ b/source/pr_cmds.c @@ -1152,60 +1152,60 @@ sets chararcter table to translate quake texts to more friendly texts ==================== */ -static char chartbl[256]; +char chartbl2[256]; void PR_CleanLogText_Init () { int i; for (i = 0; i < 256; i++) - chartbl[i] = (i&127) < 32 ? ' ' : i&127; + chartbl2[i] = (i&127) < 32 ? ' ' : i&127; - chartbl[13] = 13; - chartbl[10] = 10; + chartbl2[13] = 13; + chartbl2[10] = 10; // special cases // numbers for (i = 18; i < 28; i++) - chartbl[i] = chartbl[i + 128] = i + 30; + chartbl2[i] = chartbl2[i + 128] = i + 30; // 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] = ']'; + chartbl2[29] = chartbl2[29 + 128] = chartbl2[128] = '('; + chartbl2[31] = chartbl2[31 + 128] = chartbl2[130] = ')'; + chartbl2[16] = chartbl2[16 + 128]= '['; + chartbl2[17] = chartbl2[17 + 128] = ']'; // hash for (i = 1; i < 5; i++) - chartbl[i] = chartbl[i + 128] = '#'; + chartbl2[i] = chartbl2[i + 128] = '#'; for (i = 6; i < 10; i++) - chartbl[i] = chartbl[i + 128] = '#'; + chartbl2[i] = chartbl2[i + 128] = '#'; - chartbl[11] = chartbl[11 + 128] = '#'; + chartbl2[11] = chartbl2[11 + 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] = '.'; + chartbl2[5] = chartbl2[14] = chartbl2[15] = chartbl2[28] = chartbl2[46] = '.'; + chartbl2[5 + 128] = chartbl2[14 + 128] = chartbl2[15 + 128] = chartbl2[28 + 128] = chartbl2[46 + 128] = '.'; // left arrow - chartbl[127] = '>'; + chartbl2[127] = '>'; // right arrow - chartbl[141] = '<'; + chartbl2[141] = '<'; // '=' - chartbl[30] = chartbl[129] = chartbl[30 + 128] = '='; + chartbl2[30] = chartbl2[129] = chartbl2[30 + 128] = '='; // whitespaces - chartbl[12] = chartbl[12 + 128] = chartbl[138] = ' '; + chartbl2[12] = chartbl2[12 + 128] = chartbl2[138] = ' '; - chartbl[33] = chartbl[33 + 128]= '!'; + chartbl2[33] = chartbl2[33 + 128]= '!'; } void PR_CleanText(unsigned char *text) { while (*text) - *text = chartbl[*text++]; + *text = chartbl2[*text++]; } /* @@ -2142,10 +2142,12 @@ void PF_infokey (void) char *value; char *key; static char ov[256]; + client_t *cl; e = G_EDICT(OFS_PARM0); e1 = NUM_FOR_EDICT(e); key = G_STRING(OFS_PARM1); + cl = &svs.clients[e1-1]; if (e1 == 0) { if ((value = Info_ValueForKey (svs.info, key)) == NULL || @@ -2153,17 +2155,20 @@ void PF_infokey (void) value = Info_ValueForKey(localinfo, key); } else if (e1 <= MAX_CLIENTS) { if (!strcmp(key, "ip")) - value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].netchan.remote_address)); + value = strcpy(ov, NET_BaseAdrToString (cl->netchan.remote_address)); else if (!strcmp(key, "realip")) - value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].realip)); - else if (!strcmp(key, "ping")) { - int ping = SV_CalcPing (&svs.clients[e1-1]); + value = strcpy(ov, NET_BaseAdrToString (cl->realip)); + else if (!strcmp(key, "download")) { + sprintf(ov, "%d", cl->download != NULL ? (int)(100*cl->downloadcount/cl->downloadsize) : -1); + value = ov; + } else if (!strcmp(key, "ping")) { + int ping = SV_CalcPing (cl); sprintf(ov, "%d", ping); value = ov; } else if (!strcmp(key, "login")) - value = svs.clients[e1-1].login; + value = cl->login; else - value = Info_ValueForKey (svs.clients[e1-1].userinfo, key); + value = Info_ValueForKey (cl->userinfo, key); } else value = ""; diff --git a/source/server.h b/source/server.h index 05422353..6a5395e9 100644 --- a/source/server.h +++ b/source/server.h @@ -27,6 +27,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_SIGNON_BUFFERS 8 +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + typedef enum { ss_dead, // no map loaded ss_loading, // spawning level edicts @@ -35,6 +40,16 @@ typedef enum { // some qc commands are only valid before the server has finished // initializing (precache commands, static sounds / objects, etc) +typedef struct +{ + double time; + int num; + sizebuf_t sb; + byte buf[MAX_MSGLEN]; +} packet_t; + +#define MAX_DELAYED_PACKETS 100 + typedef struct { // qboolean active; // false when server is going down @@ -208,6 +223,8 @@ typedef struct client_s char login[16]; int logged; + int spawncount; // for tracking map changes during downloading + //===== NETWORK ============ int chokecount; @@ -217,6 +234,7 @@ typedef struct client_s int realip_num; // random value int realip_count; qboolean rip_vip; + double delay; } client_t; // a client can leave the server in one of four ways: @@ -289,7 +307,7 @@ typedef struct qboolean fixangle[MAX_CLIENTS]; float fixangletime[MAX_CLIENTS]; vec3_t angles[MAX_CLIENTS]; - char name[MAX_OSPATH], namelong[MAX_OSPATH]; + char name[MAX_OSPATH], path[MAX_OSPATH]; int parsecount; int lastwritten; demo_frame_t frames[DEMO_FRAMES]; @@ -354,6 +372,9 @@ typedef struct challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting byte *demomem; int demomemsize; + + packet_t packets[MAX_DELAYED_PACKETS]; + int num_packets; } server_static_t; //============================================================================= @@ -499,7 +520,7 @@ void SV_InitOperatorCommands (void); void SV_SendServerinfo (client_t *client); void SV_ExtractFromUserinfo (client_t *cl, qboolean namechanged); -int SV_BoundRate (int rate); +int SV_BoundRate (qboolean dl, int rate); void Master_Heartbeat (void); void Master_Packet (void); diff --git a/source/skin.c b/source/skin.c index d3796f77..aeee5df1 100644 --- a/source/skin.c +++ b/source/skin.c @@ -295,6 +295,13 @@ void Skin_NextDownload (void) va("begin %i", cl.servercount)); Cache_Report (); // print remaining memory } + + // if we were downloading before map change, continue + if (cls.download) + { + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "nextdl"); + } } diff --git a/source/sv_demo.c b/source/sv_demo.c index fff6a623..19acf0a6 100644 --- a/source/sv_demo.c +++ b/source/sv_demo.c @@ -43,6 +43,8 @@ static int demo_size; cvar_t sv_demoPrefix = {"sv_demoPrefix", ""}; cvar_t sv_demoSuffix = {"sv_demoSuffix", ""}; cvar_t sv_onrecordfinish = {"sv_onRecordFinish", ""}; +cvar_t sv_ondemoremove = {"sv_onDemoRemove", ""}; +cvar_t sv_demotxt = {"sv_demotxt", "1"}; void SV_WriteDemoMessage (sizebuf_t *msg, int type, int to, float time); size_t (*dwrite) ( const void *buffer, size_t size, size_t count, void *stream); @@ -570,6 +572,8 @@ void Demo_Init (void) Cvar_RegisterVariable (&sv_demoPrefix); Cvar_RegisterVariable (&sv_demoSuffix); Cvar_RegisterVariable (&sv_onrecordfinish); + Cvar_RegisterVariable (&sv_ondemoremove); + Cvar_RegisterVariable (&sv_demotxt); p = COM_CheckParm ("-democache"); if (p) @@ -632,14 +636,19 @@ void SV_Stop (int reason) Con_Printf ("Not recording a demo.\n"); return; } - + if (reason == 2) { + char path[MAX_OSPATH]; // stop and remove if (demo.disk) fclose(demo.file); - Sys_remove(demo.namelong); + sprintf(path, "%s/%s/%s", com_gamedir, demo.path, demo.name); + Sys_remove(path); + + strcpy(path + strlen(path) - 3, "txt"); + Sys_remove(path); demo.file = NULL; sv.demorecording = false; @@ -679,8 +688,23 @@ void SV_Stop (int reason) if (sv_onrecordfinish.string[0]) { - Cmd_TokenizeString(va("blah %s \"%s/%s\"", sv_onrecordfinish.string, sv_demoDir.string, serverdemo.string)); + extern redirect_t sv_redirected; + int old = sv_redirected; + char path[MAX_OSPATH]; + char *p; + + if ((p = strstr(sv_onrecordfinish.string, " ")) != NULL) + *p = 0; // strip parameters + + strcpy(path, demo.name); + strcpy(path + strlen(demo.name) - 3, "txt"); + + sv_redirected = RD_NONE; // onrecord script is called always from the console + Cmd_TokenizeString(va("script %s \"%s\" \"%s\" \"%s\" %s", sv_onrecordfinish.string, demo.path, serverdemo.string, path, p != NULL ? p+1 : "")); + if (p) *p = ' '; SV_Script_f(); + + sv_redirected = old; } Cvar_SetROM(&serverdemo, ""); @@ -765,17 +789,121 @@ void SV_WriteSetDemoMessage (void) fflush (demo.file); } -static void SV_Record (void) +static char *SV_PrintTeams(void) +{ + char *teams[MAX_CLIENTS], *p; + int id = 0, i, j, numcl = 0, numt = 0; + client_t *clients[MAX_CLIENTS]; + char buf[2048] = {0}; + extern cvar_t teamplay; + extern char chartbl2[]; + + // count teams and players + for (i=0; i < MAX_CLIENTS; i++) + { + if (svs.clients[i].state != cs_spawned) + continue; + if (svs.clients[i].spectator) + continue; + + clients[numcl++] = &svs.clients[i]; + for (j = 0; j < numt; j++) + if (!strcmp(svs.clients[i].team, teams[j])) + break; + if (j != numt) + continue; + + teams[numt++] = svs.clients[i].team; + } + + // create output + + if (numcl == 2) // duel + { + sprintf(buf, "team1 %s\nteam2 %s\n", clients[0]->name, clients[1]->name); + } else if (!teamplay.value) // ffa + { + sprintf(buf, "players:\n"); + for (i = 0; i < numcl; i++) + sprintf(buf+strlen(buf), " %s\n", clients[i]->name); + } else { // teamplay + for (j = 0; j < numt; j++) { + sprintf(buf + strlen(buf), "team %s:\n", teams[j]); + for (i = 0; i < numcl; i++) + if (!strcmp(clients[i]->team, teams[j])) + sprintf(buf + strlen(buf), " %s\n", clients[i]->name); + } + } + + if (!numcl) + return "\n"; + for (p = buf; *p; p++) *p = chartbl2[(byte)*p]; + return va("%s",buf); +} + +static void SV_Record (char *name) { sizebuf_t buf; char buf_data[MAX_MSGLEN]; int n, i; - char *s, info[MAX_INFO_STRING]; + char *s, info[MAX_INFO_STRING], path[MAX_OSPATH]; client_t *player; char *gamedir; int seq = 1; + memset(&demo, 0, sizeof(demo)); + for (i = 0; i < UPDATE_BACKUP; i++) + demo.recorder.frames[i].entities.entities = demo_entities[i]; + + DemoBuffer_Init(&demo.dbuffer, demo.buffer, sizeof(demo.buffer)); + DemoSetMsgBuf(NULL, &demo.frames[0].buf); + + demo.datagram.maxsize = sizeof(demo.datagram_data); + demo.datagram.data = demo.datagram_data; + + demo.file = fopen (name, "wb"); + if (!demo.file) + { + Con_Printf ("ERROR: couldn't open %s\n", name); + return; + } + + SV_InitRecord(); + + s = name + strlen(name); + while (*s != '/') s--; + Q_strncpyz(demo.name, s+1, sizeof(demo.name)); + Q_strncpyz(demo.path, sv_demoDir.string, sizeof(demo.path)); + + if (!*demo.path) + strcpy(demo.path, "."); + + SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n", demo.disk ? "disk" : "memory", demo.name); + Cvar_SetROM(&serverdemo, demo.name); + + strcpy(path, name); + strcpy(path + strlen(path)-3, "txt"); + + if (sv_demotxt.value) { + FILE *f; + + f = fopen (path, "w+t"); + if (f != NULL) + { + char buf[2000]; + date_t date; + + Sys_TimeOfDay(&date); + + sprintf(buf, "date %s\nmap %s\nteamplay %d\ndeathmatch %d\ntimelimit %d\n%s",date.str, sv.name, (int)teamplay.value, (int)deathmatch.value, (int)timelimit.value, SV_PrintTeams()); + fwrite(buf, strlen(buf),1,f); + fflush(f); + fclose(f); + } + } else + Sys_remove(path); + sv.demorecording = true; demo.pingtime = demo.time = sv.time; @@ -1107,34 +1235,8 @@ void SV_Record_f (void) // COM_ForceExtension (name, ".mvd"); - memset(&demo, 0, sizeof(demo)); - for (i = 0; i < UPDATE_BACKUP; i++) - demo.recorder.frames[i].entities.entities = demo_entities[i]; - - DemoBuffer_Init(&demo.dbuffer, demo.buffer, sizeof(demo.buffer)); - DemoSetMsgBuf(NULL, &demo.frames[0].buf); - demo.datagram.maxsize = sizeof(demo.datagram_data); - demo.datagram.data = demo.datagram_data; - - demo.file = fopen (name, "wb"); - if (!demo.file) - { - Con_Printf ("ERROR: couldn't open.\n"); - return; - } - - SV_InitRecord(); - - Q_strncpyz(demo.namelong, name, sizeof(demo.namelong)); - - s = name + strlen(name); - while (*s != '/') s--; - Q_strncpyz(demo.name, s+1, sizeof(demo.name)); - - SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n", demo.disk ? "disk" : "memory", demo.name); - Cvar_SetROM(&serverdemo, demo.name); - SV_Record (); + SV_Record (name); } /* @@ -1282,37 +1384,8 @@ void SV_EasyRecord_f (void) } while (f); } -// -// open the demo file -// - memset(&demo, 0, sizeof(demo)); - for (i = 0; i < UPDATE_BACKUP; i++) - demo.recorder.frames[i].entities.entities = demo_entities[i]; - - DemoBuffer_Init(&demo.dbuffer, demo.buffer, sizeof(demo.buffer)); - DemoSetMsgBuf(NULL, &demo.frames[0].buf); - - demo.datagram.maxsize = sizeof(demo.datagram_data); - demo.datagram.data = demo.datagram_data; - - demo.file = fopen (name2, "wb"); - if (!demo.file) - { - Con_Printf ("ERROR: couldn't open %s\n", name2); - return; - } - - SV_InitRecord(); - Q_strncpyz(demo.namelong, name2, sizeof(demo.namelong)); - - s = name2 + strlen(name2); - while (*s != '/') s--; - Q_strncpyz(demo.name, s+1, sizeof(demo.name)); - - SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n", demo.disk ? "disk" : "memory", demo.name); - Cvar_SetROM(&serverdemo, demo.name); - SV_Record (); + SV_Record (name2); } void SV_DemoList_f (void) @@ -1378,6 +1451,28 @@ char *SV_DemoNum(int num) return NULL; } +char *SV_DemoName2Txt(char *name) +{ + char s[MAX_OSPATH]; + + if (!name) + return NULL; + + strcpy(s, name); + + if (strstr(s, ".mvd.gz") != NULL) + strcpy(s + strlen(s) - 6, "txt"); + else + strcpy(s + strlen(s) - 3, "txt"); + + return va("%s", s); +} + +char *SV_DemoTxTNum(int num) +{ + SV_DemoName2Txt(SV_DemoNum(num)); +} + void SV_DemoRemove_f (void) { char name[MAX_DEMO_NAME], *ptr; @@ -1414,6 +1509,8 @@ void SV_DemoRemove_f (void) Con_Printf("removing %s...\n", list->name); i++; } + + Sys_remove(SV_DemoName2Txt(path)); } } @@ -1434,10 +1531,24 @@ void SV_DemoRemove_f (void) if (sv.demorecording && !strcmp(name, demo.name)) SV_Stop_f(); - if (!Sys_remove(path)) + if (!Sys_remove(path)) { Con_Printf("demo %s succesfully removed\n", name); - else + + if (*sv_ondemoremove.string) + { + extern redirect_t sv_redirected; + int old = sv_redirected; + + sv_redirected = RD_NONE; // this script is called always from the console + Cmd_TokenizeString(va("script %s \"%s\" \"%s\"", sv_ondemoremove.string, sv_demoDir.string, name)); + SV_Script_f(); + + sv_redirected = old; + } + } else Con_Printf("unable to remove demo %s\n", name); + + Sys_remove(SV_DemoName2Txt(path)); } void SV_DemoRemoveNum_f (void) @@ -1466,10 +1577,147 @@ void SV_DemoRemoveNum_f (void) SV_Stop_f(); sprintf(path, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); - if (!Sys_remove(path)) + if (!Sys_remove(path)) { Con_Printf("demo %s succesfully removed\n", name); - else + if (*sv_ondemoremove.string) + { + extern redirect_t sv_redirected; + int old = sv_redirected; + + sv_redirected = RD_NONE; // this script is called always from the console + Cmd_TokenizeString(va("script %s \"%s\" \"%s\"", sv_ondemoremove.string, sv_demoDir.string, name)); + SV_Script_f(); + + sv_redirected = old; + } + } else Con_Printf("unable to remove demo %s\n", name); + + Sys_remove(SV_DemoName2Txt(path)); } else Con_Printf("invalid demo num\n"); } + +void SV_DemoInfoAdd_f (void) +{ + char *name, *args, path[MAX_OSPATH]; + FILE *f; + + if (Cmd_Argc() < 3) { + Con_Printf("usage:demoInfoAdd \n = * for currently recorded demo\n"); + return; + } + + if (!strcmp(Cmd_Argv(1), "*")) + { + if (!sv.demorecording) { + Con_Printf("Not recording demo!\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, demo.path, SV_DemoName2Txt(demo.name)); + } else { + name = SV_DemoTxTNum(atoi(Cmd_Argv(1))); + + if (!name) { + Con_Printf("invalid demo num\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + } + + if ((f = fopen(path, "a+t")) == NULL) + { + Con_Printf("faild to open the file\n"); + return; + } + + // skip demonum + args = Cmd_Args(); + while (*args > 32) args++; + while (*args && *args <= 32) args++; + + fwrite(args, strlen(args), 1, f); + fwrite("\n", 1, 1, f); + fflush(f); + fclose(f); +} + +void SV_DemoInfoRemove_f (void) +{ + char *name, path[MAX_OSPATH]; + + if (Cmd_Argc() < 2) { + Con_Printf("usage:demoInfoRemove \n = * for currently recorded demo\n"); + return; + } + + if (!strcmp(Cmd_Argv(1), "*")) + { + if (!sv.demorecording) { + Con_Printf("Not recording demo!\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, demo.path, SV_DemoName2Txt(demo.name)); + } else { + name = SV_DemoTxTNum(atoi(Cmd_Argv(1))); + + if (!name) { + Con_Printf("invalid demo num\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + } + + if (Sys_remove(path)) + Con_Printf("failed to remove the file\n"); + else Con_Printf("file removed\n"); +} + +void SV_DemoInfo_f (void) +{ + char buf[64]; + FILE *f = NULL; + char *name, path[MAX_OSPATH]; + + if (Cmd_Argc() < 2) { + Con_Printf("usage:demoinfo \n = * for currently recorded demo\n"); + return; + } + + if (!strcmp(Cmd_Argv(1), "*")) + { + if (!sv.demorecording) { + Con_Printf("Not recording demo!\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, demo.path, SV_DemoName2Txt(demo.name)); + } else { + name = SV_DemoTxTNum(atoi(Cmd_Argv(1))); + + if (!name) { + Con_Printf("invalid demo num\n"); + return; + } + + sprintf(path, "%s/%s/%s", com_gamedir, sv_demoDir.string, name); + } + + if ((f = fopen(path, "rt")) == NULL) + { + Con_Printf("(empty)\n"); + return; + } + + while (!feof(f)) + { + buf[fread (buf, 1, sizeof(buf)-1, f)] = 0; + Con_Printf("%s", buf); + } + + fclose(f); +} diff --git a/source/sv_init.c b/source/sv_init.c index bd6d2d97..3dbd23c9 100644 --- a/source/sv_init.c +++ b/source/sv_init.c @@ -295,6 +295,7 @@ void SV_SpawnServer (char *server) Con_DPrintf ("SpawnServer: %s\n",server); SV_SaveSpawnparms (); + SV_LoadAccounts(); svs.spawncount++; // any partially connected client will be // restarted @@ -305,8 +306,6 @@ void SV_SpawnServer (char *server) Mod_ClearAll (); Hunk_FreeToLowMark (host_hunklevel); - //Sys_Sleep(100); - if (coop.value) Cvar_Set (&deathmatch, "0"); current_skill = (int)(skill.value + 0.5); @@ -343,13 +342,10 @@ void SV_SpawnServer (char *server) // which determines how big each edict is PR_LoadProgs (); - //Sys_Sleep(100); // allocate edicts sv.edicts = Hunk_AllocName (MAX_EDICTS*pr_edict_size, "edicts"); - //Sys_Sleep(100); - // leave slots at start for clients only sv.num_edicts = MAX_CLIENTS+1; for (i=0 ; iuse == use_log) fprintf(f, "%s %s %d %d\n", acc->login, acc->pass, acc->state, acc->failures); else - fprintf(f, "%s %d\n", acc->login, acc->state); + fprintf(f, "%s %s %d\n", acc->login, acc->pass, acc->state); c++; } @@ -110,12 +110,21 @@ void SV_LoadAccounts(void) { int i,c; FILE *f; - char tmp[128]; + char *ip; account_t *acc = accounts; + client_t *cl; - if ( (f = fopen( ACC_DIR "/" ACC_FILE ,"rt")) == NULL) + if ( (f = fopen( va("%s\\" ACC_FILE, com_gamedir) ,"rt")) == NULL) { Con_Printf("couldn't open " ACC_FILE "\n"); + // logout + num_accounts = 0; + for (cl = svs.clients; cl - svs.clients < MAX_CLIENTS; cl++) + { + if (cl->logged > 0) + cl->logged = 0; + cl->login[0] = 0; + } return; } @@ -128,7 +137,7 @@ void SV_LoadAccounts(void) { strcpy(acc->pass, acc->login); acc->use = use_ip; - fscanf(f, "%d\n", &acc->state); + fscanf(f, "%s %d\n", acc->pass, &acc->state); } else fscanf(f, "%s %d %d\n", acc->pass, &acc->state, &acc->failures); @@ -139,6 +148,38 @@ void SV_LoadAccounts(void) num_accounts = acc - accounts; fclose(f); + + // for every connected client check if their login is still valid + for (cl = svs.clients; cl - svs.clients < MAX_CLIENTS; cl++) + { + if (cl->state < cs_connected) + continue; + + if (cl->logged <= 0) + continue; + + for (i = 0, acc = accounts; i < num_accounts; i++, acc++) + if ( (acc->use == use_log && !strcmp(acc->login, cl->login)) + || (acc->use == use_ip && !strcmp(acc->login, va("%d.%d.%d.%d", cl->realip.ip[0], cl->realip.ip[1], cl->realip.ip[2], cl->realip.ip[3]))) ) + break; + + if (i < num_accounts && acc->state == a_ok) { + // login again if possible + if (!acc->inuse || acc->use == use_ip) + { + cl->logged = i+1; + if (acc->use == use_ip) + Q_strncpyz(cl->login, acc->pass, sizeof(cl->login)); + + acc->inuse++; + continue; + } + } + // login is not valid anymore, logout + cl->logged = 0; + cl->login[0] = 0; + } + } @@ -161,7 +202,7 @@ void SV_CreateAccount_f(void) if (Cmd_Argc() < 2) { - Con_Printf("usage: acc_create []\n acc_create \nmaximum %d characters for login/pass\n", MAX_LOGINNAME - 1); + Con_Printf("usage: acc_create []\n acc_create \nmaximum %d characters for login/pass\n", MAX_LOGINNAME - 1); return; } @@ -171,9 +212,14 @@ void SV_CreateAccount_f(void) return; } - if (StringToFilter(Cmd_Argv(1), &adr)) + if (StringToFilter(Cmd_Argv(1), &adr)) { use = use_ip; - else { + if (Cmd_Argc() < 3) + { + Con_Printf("usage: acc_create \nmaximum %d characters for username\n", MAX_LOGINNAME - 1); + return; + } + } else { use = use_log; // validate user login/pass @@ -198,7 +244,7 @@ void SV_CreateAccount_f(void) continue; } - if (!stricmp(accounts[i].login, Cmd_Argv(1))) + if (!stricmp(accounts[i].login, Cmd_Argv(1)) || (use == use_ip && !stricmp(accounts[i].login, Cmd_Argv(2)))) break; c++; @@ -390,15 +436,15 @@ int checklogin(char *log, char *pass, int num, int use) if (use == accounts[i].use && /*use == use_log && accounts[i].use == use_log && */!stricmp(log, accounts[i].login)) { - if (accounts[i].inuse) + if (accounts[i].inuse && accounts[i].use == use_log) return -1; if (accounts[i].state == a_blocked) return -2; - if (!stricmp(pass, accounts[i].pass)) { + if (use == use_ip || !stricmp(pass, accounts[i].pass)) { accounts[i].failures = 0; - accounts[i].inuse = num; + accounts[i].inuse++; return i+1; } @@ -413,19 +459,6 @@ int checklogin(char *log, char *pass, int num, int use) return 0; } - /*if (use == use_ip && accounts[i].use == use_ip && ) - { - if (accounts[i].inuse) - return -1; - - if (accounts[i].state == a_blocked) - return -2; - - accounts[i].inuse = num; - return i+1; - } - */ - c++; } @@ -443,7 +476,7 @@ void Login_Init (void) Cmd_AddCommand ("acc_block",SV_BlockAccount_f); // load account list - SV_LoadAccounts(); + //SV_LoadAccounts(); } /* @@ -481,7 +514,7 @@ qboolean SV_Login(client_t *cl) ip = va("%d.%d.%d.%d", cl->realip.ip[0], cl->realip.ip[1], cl->realip.ip[2], cl->realip.ip[3]); if (cl->logged = checklogin(ip, ip, cl - svs.clients + 1, use_ip) > 0) { - strcpy(cl->login, ip); + strcpy(cl->login, accounts[cl->logged-1].pass); return true; } @@ -499,7 +532,7 @@ qboolean SV_Login(client_t *cl) void SV_Logout(client_t *cl) { if (cl->logged > 0) { - accounts[cl->logged-1].inuse = false; + accounts[cl->logged-1].inuse--; cl->login[0] = 0; cl->logged = 0; } diff --git a/source/sv_main.c b/source/sv_main.c index 36447328..3c0ad458 100644 --- a/source/sv_main.c +++ b/source/sv_main.c @@ -85,6 +85,11 @@ cvar_t sv_demoMaxDirSize = {"sv_demoMaxDirSize", "102400"}; qboolean sv_demoDir_OnChange(cvar_t *cvar, char *value); cvar_t sv_demoDir = {"sv_demoDir", "demos", 0, sv_demoDir_OnChange}; +cvar_t sv_getrealip = {"sv_getrealip", "1"}; +cvar_t sv_minping = {"sv_minping", "0"}; +cvar_t sv_serverip = {"sv_serverip", ""}; +cvar_t sv_maxdownloadrate = {"sv_maxdownloadrate", "0"}; + // // game rules mirrored in svs.info // @@ -787,7 +792,6 @@ void SVC_DirectConnect (void) *newcl = temp; for (i = 0; i < UPDATE_BACKUP; i++) newcl->frames[i].entities.entities = cl_entities[newcl-svs.clients][i]; - Netchan_OutOfBandPrint (net_serversocket, adr, "%c", S2C_CONNECTION ); @@ -1232,9 +1236,16 @@ SV_AddIP_f void SV_AddIP_f (void) { int i; + ipfilter_t f; + + if (!StringToFilter (Cmd_Argv(1), &f)) { + Con_Printf ("Bad filter address: %s\n", Cmd_Argv(1)); + return; + } for (i=0 ; i 32) @@ -1439,8 +1448,13 @@ char *DecodeArgs(char *args) value = Info_ValueForKey(localinfo, key); *p++ = '\"'; - if (value) while (*value) - *p++ = *value++; + if (ch == '$') { + if (value) while (*value) + *p++ = chartbl2[(byte)*value++]; + } else { + if (value) while (*value) + *p++ = *value++; + } *p++ = '\"'; } else while (*args > 32) *p++ = *args++; @@ -1456,6 +1470,7 @@ void SV_Script_f (void) char *path, *p; char args[1024]; int i; + extern redirect_t sv_redirected; if (Cmd_Argc() < 2) { Con_Printf("usage: script []\n"); @@ -1464,14 +1479,15 @@ void SV_Script_f (void) path = Cmd_Argv(1); - if (path[0] == '.' && path[1] == '.') - path += 2; + if (!strncmp(path, "../", 3) || !strncmp(path, "..\\", 3)) + path += 3; - if (strstr(path,"/..")) { + if (strstr(path,"../") || strstr(path,"..\\")) { Con_Printf("invalid path\n"); return; } + path = Cmd_Argv(1); p = Cmd_Args(); while (*p > 32) @@ -1480,20 +1496,12 @@ void SV_Script_f (void) p++; p = DecodeArgs(p); - - /*args[0] = 0; - for (i = 2; i < Cmd_Argc(); i++) - sprintf(args + strlen(args), "\"%s\" ", Cmd_Argv(i)); - */ -#ifdef _WIN32 - if (!Sys_Script(path, p)) - Con_Printf("Couldn't run script %s.bat\n", Cmd_Argv(1)); - else - Con_Printf("Runnig %s.bat\n", Cmd_Argv(1)); -#else - Sys_Script(path, p); -#endif + if (sv_redirected != RD_MOD) + Sys_Printf("Running %s.qws\n", path); + + Sys_Script(path, va("%d %s",sv_redirected, p)); + } //============================================================================ @@ -1506,7 +1514,10 @@ SV_ReadPackets void SV_ReadPackets (void) { int i; + unsigned seq; client_t *cl; + packet_t *pack, tmp; + double time; qboolean good; int qport; @@ -1530,7 +1541,7 @@ void SV_ReadPackets (void) // stupid address translating routers MSG_BeginReading (); MSG_ReadLong (); // sequence number - MSG_ReadLong (); // sequence number + seq = MSG_ReadLong () & ~(1<<31); // sequence number qport = MSG_ReadShort () & 0xffff; // check for packets from connected clients @@ -1547,6 +1558,20 @@ void SV_ReadPackets (void) Con_DPrintf ("SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; } + + if (svs.num_packets == MAX_DELAYED_PACKETS) // packet has to be dropped.. + break; + + pack = &svs.packets[svs.num_packets]; + + svs.num_packets++; + + pack->time = realtime; + pack->num = i; + SZ_Clear(&pack->sb); + SZ_Write(&pack->sb, net_message.data, net_message.cursize); + break; + if (Netchan_Process(&cl->netchan)) { // this is a valid, sequenced packet, so process it svs.stats.packets++; @@ -1567,6 +1592,55 @@ void SV_ReadPackets (void) } } +/* +================= +SV_ReadDelayedPackets +================= +*/ +void SV_ReadDelayedPackets (void) +{ + int i, j, num = 0; + client_t *cl; + packet_t *pack; + + for (i = 0, pack = svs.packets; i < svs.num_packets;) + { + if (realtime < pack->time + svs.clients[pack->num].delay) { + i++; + pack++; + continue; + } + + num++; + + SZ_Clear(&net_message); + SZ_Write(&net_message, pack->sb.data, pack->sb.cursize); + cl = &svs.clients[pack->num]; + net_from = cl->netchan.remote_address; + + if (Netchan_Process(&cl->netchan)) + { // this is a valid, sequenced packet, so process it + svs.stats.packets++; + cl->send_message = true; // reply at end of frame + if (cl->state != cs_zombie) + SV_ExecuteClientMessage (cl); + } + + for (j = i+1; j < svs.num_packets; j++) { + SZ_Clear(&svs.packets[j-1].sb); + SZ_Write(&svs.packets[j-1].sb, svs.packets[j].sb.data, svs.packets[j].sb.cursize); + svs.packets[j-1].num = svs.packets[j].num; + svs.packets[j-1].time = svs.packets[j].time; + } + + svs.num_packets--; + //i = 0; + //pack = svs.packets; + } + + //svs.num_packets -= num; +} + /* ================== SV_CheckTimeouts @@ -1641,12 +1715,21 @@ void SV_GetConsoleCommands (void) SV_BoundRate =================== */ -int SV_BoundRate (int rate) +int SV_BoundRate (qboolean dl, int rate) { if (!rate) rate = 2500; - if (sv_maxrate.value && rate > sv_maxrate.value) - rate = sv_maxrate.value; + if (dl) + { + if (!sv_maxdownloadrate.value && sv_maxrate.value && rate > sv_maxrate.value) + rate = sv_maxrate.value; + + if (sv_maxdownloadrate.value && rate > sv_maxdownloadrate.value) + rate = sv_maxdownloadrate.value; + } else + if (sv_maxrate.value && rate > sv_maxrate.value) + rate = sv_maxrate.value; + if (rate < 500) rate = 500; if (rate > 100000) @@ -1666,7 +1749,7 @@ SV_CheckVars void SV_CheckVars (void) { static char pw[MAX_INFO_STRING]="", spw[MAX_INFO_STRING]="", vspw[MAX_INFO_STRING]=""; - static float old_maxrate = 0; + static float old_maxrate = 0, old_maxdlrate = 0; int v; // check password and spectator_password @@ -1696,20 +1779,27 @@ void SV_CheckVars (void) } // check sv_maxrate - if (sv_maxrate.value != old_maxrate) { + if (sv_maxrate.value != old_maxrate || sv_maxdownloadrate.value != old_maxdlrate ) { client_t *cl; int i; char *val; old_maxrate = sv_maxrate.value; + old_maxdlrate = sv_maxdownloadrate.value; for (i=0, cl = svs.clients ; istate < cs_preconnected) continue; - val = Info_ValueForKey (cl->userinfo, "rate"); - cl->netchan.rate = 1.0 / SV_BoundRate (atoi(val)); + if (cl->download) { + val = Info_ValueForKey (cl->userinfo, "drate"); + if (!*val) + val = Info_ValueForKey (cl->userinfo, "rate"); + } else + val = Info_ValueForKey (cl->userinfo, "rate"); + + cl->netchan.rate = 1.0 / SV_BoundRate (cl->download != NULL, atoi(val)); } } } @@ -1801,6 +1891,10 @@ void SV_Frame (double time) // get packets SV_ReadPackets (); + +// check delayed packets + SV_ReadDelayedPackets (); + // move autonomous things around if enough time has passed if (!sv.paused) SV_Physics (); @@ -1845,6 +1939,9 @@ void SV_DemoList_f (void); void SV_DemoRemove_f (void); void SV_DemoRemoveNum_f (void); void SV_Cancel_f (void); +void SV_DemoInfoAdd_f (void); +void SV_DemoInfoRemove_f (void); +void SV_DemoInfo_f (void); void SV_InitLocal (void) { @@ -1866,7 +1963,11 @@ void SV_InitLocal (void) SV_InitOperatorCommands (); SV_UserInit (); - + + Cvar_RegisterVariable (&sv_getrealip); + Cvar_RegisterVariable (&sv_maxdownloadrate); + Cvar_RegisterVariable (&sv_minping); + Cvar_RegisterVariable (&sv_serverip); Cvar_RegisterVariable (&sv_cpserver); Cvar_RegisterVariable (&rcon_password); Cvar_RegisterVariable (&password); @@ -1947,6 +2048,9 @@ void SV_InitLocal (void) Cmd_AddCommand ("rmdemo", SV_DemoRemove_f); Cmd_AddCommand ("rmdemonum", SV_DemoRemoveNum_f); Cmd_AddCommand ("script", SV_Script_f); + Cmd_AddCommand ("demoInfoAdd", SV_DemoInfoAdd_f); + Cmd_AddCommand ("demoInfoRemove", SV_DemoInfoRemove_f); + Cmd_AddCommand ("demoInfo", SV_DemoInfo_f); for (i=0 ; iteam, Info_ValueForKey (cl->userinfo, "team"), sizeof(cl->team)); // rate - val = Info_ValueForKey (cl->userinfo, "rate"); - cl->netchan.rate = 1.0 / SV_BoundRate (atoi(val)); + if (cl->download) { + val = Info_ValueForKey (cl->userinfo, "drate"); + if (!atoi(val)) + val = Info_ValueForKey (cl->userinfo, "rate"); + } else + val = Info_ValueForKey (cl->userinfo, "rate"); + cl->netchan.rate = 1.0 / SV_BoundRate (cl->download != NULL, atoi(val)); // message level val = Info_ValueForKey (cl->userinfo, "msg"); diff --git a/source/sv_sys_unix.c b/source/sv_sys_unix.c index 53abf8bc..a36f98cd 100644 --- a/source/sv_sys_unix.c +++ b/source/sv_sys_unix.c @@ -341,36 +341,23 @@ int NET_Sleep(double sec) void Sys_Sleep(unsigned long ms) { - usleep(ms * 1000); + usleep(ms*1000); } int Sys_Script(char *path, char *args) { char str[1024]; - sprintf(str,"cd %s\n./%s.qws %s\ncd ..", com_gamedir, path, args); + sprintf(str,"cd %s\n./%s.qws %s &\ncd ..", com_gamedir, path, args); if (system(str) == -1) return 0; return 1; - -#if 0 - Cmd_TokenizeString(args); - for (i = 0; i < Cmd_Argc() && i < MAXSCRIPTARGS; i++) - Args[i] = Cmd_Argv(i); - - Args[i] = NULL; - - - if (_spawnv(_P_WAITNO, va("%s\\%s",com_gamedir, path), args) == -1) - return 0; - - return 1; -#endif } + /* ============= main diff --git a/source/sv_sys_win.c b/source/sv_sys_win.c index 6e0bd60e..fba347bc 100644 --- a/source/sv_sys_win.c +++ b/source/sv_sys_win.c @@ -406,12 +406,12 @@ int Sys_Script(char *path, char *args) si.wShowWindow = SW_SHOWMINNOACTIVE; GetCurrentDirectory(sizeof(curdir), curdir); + + sprintf(cmdline, "%s\\sh.exe %s.qws %s", curdir, path, args); strcat(curdir,va("\\%s", com_gamedir+2)); - sprintf(cmdline, "%s\\%s.bat %s", curdir, path, args); - return CreateProcess (NULL, cmdline, NULL, NULL, - FALSE, DETACHED_PROCESS/*CREATE_NEW_CONSOLE*/ , NULL, curdir, &si, &pi); + FALSE, DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ , NULL, curdir, &si, &pi); } /* ================== diff --git a/source/sv_user.c b/source/sv_user.c index 72a1b61e..4920079f 100644 --- a/source/sv_user.c +++ b/source/sv_user.c @@ -61,25 +61,30 @@ void SV_New_f (void) char *gamedir; int playernum; extern cvar_t sv_login; + extern cvar_t sv_serverip; + extern cvar_t sv_getrealip; if (host_client->state == cs_spawned) return; - if (!host_client->connection_started) + if (!host_client->connection_started || host_client->state == cs_connected) host_client->connection_started = realtime; + host_client->spawncount = svs.spawncount; // do not proceed if realip is unknown - if (host_client->realip.ip[0] == 0) + if (host_client->state == cs_preconnected && host_client->realip.ip[0] == 0 && sv_getrealip.value) { + host_client->state = cs_preconnected; MSG_WriteByte (&host_client->netchan.message, svc_stufftext); - MSG_WriteString (&host_client->netchan.message, va("packet %s \"ip %d %d\"\ncmd new\n", NET_AdrToString(net_local_adr), host_client - svs.clients, host_client->realip_num)); + MSG_WriteString (&host_client->netchan.message, va("packet %s \"ip %d %d\"\ncmd new\n", + sv_serverip.string[0] ? sv_serverip.string : NET_AdrToString(net_local_adr), host_client - svs.clients, host_client->realip_num)); if (realtime - host_client->connection_started > 5) { - Netchan_OutOfBandPrint (net_serversocket, net_from, "%c\nfaild to validate client's IP\n\n", A2C_PRINT); - SV_DropClient (host_client); - } - - return; + host_client->state = cs_connected; + //Netchan_OutOfBandPrint (net_serversocket, net_from, "%c\nfaild to validate client's IP\n\n", A2C_PRINT); + //SV_DropClient (host_client); + } else + return; } // rip_vip means that client can be connected if he has VIP for he's real ip @@ -113,86 +118,17 @@ void SV_New_f (void) Info_SetValueForStarKey (host_client->userinfo, "*VIP", host_client->vip ? va("%d", host_client->vip) : "", MAX_INFO_STRING); - if (!SV_Login(host_client)) - return; - // now we are connected host_client->state = cs_connected; } - if (!host_client->logged && sv_login.value) - return; // not so fast; - -// send the info about the new client to all connected clients -// SV_FullClientUpdate (host_client, &sv.reliable_datagram); -// host_client->sendinfo = true; - - gamedir = Info_ValueForKey (svs.info, "*gamedir"); - if (!gamedir[0]) - gamedir = "qw"; - -//NOTE: This doesn't go through ClientReliableWrite since it's before the user -//spawns. These functions are written to not overflow - if (host_client->num_backbuf) { - Con_Printf("WARNING %s: [SV_New] Back buffered (%d0), clearing\n", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; - SZ_Clear(&host_client->netchan.message); - } - - // send the serverdata - MSG_WriteByte (&host_client->netchan.message, svc_serverdata); - MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION); - MSG_WriteLong (&host_client->netchan.message, svs.spawncount); - MSG_WriteString (&host_client->netchan.message, gamedir); - - playernum = NUM_FOR_EDICT(host_client->edict)-1; - if (host_client->spectator) - playernum |= 128; - MSG_WriteByte (&host_client->netchan.message, playernum); - - // send full levelname - MSG_WriteString (&host_client->netchan.message, PR_GetString(sv.edicts->v.message)); - - // send the movevars - MSG_WriteFloat(&host_client->netchan.message, movevars.gravity); - MSG_WriteFloat(&host_client->netchan.message, movevars.stopspeed); - MSG_WriteFloat(&host_client->netchan.message, movevars.maxspeed); - MSG_WriteFloat(&host_client->netchan.message, movevars.spectatormaxspeed); - MSG_WriteFloat(&host_client->netchan.message, movevars.accelerate); - MSG_WriteFloat(&host_client->netchan.message, movevars.airaccelerate); - MSG_WriteFloat(&host_client->netchan.message, movevars.wateraccelerate); - MSG_WriteFloat(&host_client->netchan.message, movevars.friction); - MSG_WriteFloat(&host_client->netchan.message, movevars.waterfriction); - MSG_WriteFloat(&host_client->netchan.message, movevars.entgravity); - - // send music - MSG_WriteByte (&host_client->netchan.message, svc_cdtrack); - MSG_WriteByte (&host_client->netchan.message, sv.edicts->v.sounds); - - // send server info string - MSG_WriteByte (&host_client->netchan.message, svc_stufftext); - MSG_WriteString (&host_client->netchan.message, va("fullserverinfo \"%s\"\n", svs.info) ); -} - -void SV_New2_f (void) -{ - char *gamedir; - int playernum; - extern cvar_t sv_login; - - if (host_client->state == cs_spawned) + if (!SV_Login(host_client)) return; - if (host_client->realip.ip[0] == 0) - return; // don't cheat! - if (!host_client->logged && sv_login.value) return; // not so fast; - host_client->state = cs_connected; - //host_client->connection_started = realtime; - - // send the info about the new client to all connected clients +// send the info about the new client to all connected clients // SV_FullClientUpdate (host_client, &sv.reliable_datagram); // host_client->sendinfo = true; @@ -335,7 +271,8 @@ void SV_Modellist_f (void) //spawns. These functions are written to not overflow if (host_client->num_backbuf) { Con_Printf("WARNING %s: [SV_Modellist] Back buffered (%d0), clearing\n", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; + host_client->num_backbuf = 1; + SZ_Clear(&host_client->netchan.message); } @@ -626,17 +563,19 @@ void SV_Begin_f (void) //check he's not cheating - if ( !*Info_ValueForKey (host_client->userinfo, "pmodel") || - !*Info_ValueForKey (host_client->userinfo, "pmodel")) - { - SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: missing player/eyes model checksum\n", host_client->name); - } else { - pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel")); - emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel")); - - if (pmodel != sv.model_player_checksum || - emodel != sv.eyes_player_checksum) - SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name); + if (!host_client->spectator) { + if ( !*Info_ValueForKey (host_client->userinfo, "pmodel") || + !*Info_ValueForKey (host_client->userinfo, "pmodel")) + { + SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: missing player/eyes model checksum\n", host_client->name); + } else { + pmodel = atoi(Info_ValueForKey (host_client->userinfo, "pmodel")); + emodel = atoi(Info_ValueForKey (host_client->userinfo, "emodel")); + + if (pmodel != sv.model_player_checksum || + emodel != sv.eyes_player_checksum) + SV_BroadcastPrintf (PRINT_HIGH, "%s WARNING: non standard player/eyes model detected\n", host_client->name); + } } sv.paused &= ~2; // FIXME!!! -- Tonik @@ -673,16 +612,35 @@ SV_NextDownload_f void SV_NextDownload_f (void) { byte buffer[1024]; - int r; + int r, tmp; int percent; int size; + double clear, frametime; if (!host_client->download) return; - r = host_client->downloadsize - host_client->downloadcount; - if (r > 768) - r = 768; + tmp = host_client->downloadsize - host_client->downloadcount; + + if ((clear = host_client->netchan.cleartime) < realtime) + clear = realtime; + + frametime = max(0.05, min(0, host_client->netchan.frame_rate)); + //Sys_Printf("rate:%f\n", host_client->netchan.frame_rate); + + r = (int)((realtime + frametime - host_client->netchan.cleartime)/host_client->netchan.rate); + if (r <= 10) + r = 10; + if (r > 1000) + r = 1000; + + // don't send too much if already buffering + if (host_client->num_backbuf) + r = 10; + + if (r > tmp) + r = tmp; + r = fread (buffer, 1, r, host_client->download); ClientReliableWrite_Begin (host_client, svc_download, 6+r); ClientReliableWrite_Short (host_client, r); @@ -701,6 +659,15 @@ void SV_NextDownload_f (void) fclose (host_client->download); host_client->download = NULL; + // if map changed tell the client to reconnect + if (host_client->spawncount != svs.spawncount) + { + char *str = "changing\nreconnect\n"; + + ClientReliableWrite_Begin (host_client, svc_stufftext, strlen(str)+2); + ClientReliableWrite_String (host_client, str); + } + } void OutofBandPrintf(netadr_t where, char *fmt, ...) @@ -797,7 +764,7 @@ SV_BeginDownload_f */ void SV_BeginDownload_f(void) { - char *name, n[MAX_OSPATH]; + char *name, n[MAX_OSPATH], *val; extern cvar_t allow_download; extern cvar_t allow_download_skins; extern cvar_t allow_download_models; @@ -806,6 +773,7 @@ void SV_BeginDownload_f(void) extern cvar_t allow_download_demos; extern cvar_t sv_demoDir; extern int file_from_pak; // ZOID did file come from pak? + extern cvar_t sv_maxdownloadrate; name = Cmd_Argv(1); // hacked by zoid to allow more conrol over download @@ -838,6 +806,8 @@ void SV_BeginDownload_f(void) if (host_client->download) { fclose (host_client->download); host_client->download = NULL; + val = Info_ValueForKey (host_client->userinfo, "rate"); + host_client->netchan.rate = 1.0/SV_BoundRate(false, atoi(val)); } if ( !strncmp(name, "demos/", 6) && sv_demoDir.string[0]) { @@ -902,6 +872,10 @@ void SV_BeginDownload_f(void) return; } + val = Info_ValueForKey (host_client->userinfo, "drate"); + if (atoi(val)) + host_client->netchan.rate = 1.0/SV_BoundRate(true, atoi(val)); + SV_NextDownload_f (); Sys_Printf ("Downloading %s to %s\n", name, host_client->name); } @@ -1090,7 +1064,7 @@ void SV_Pings_f (void) for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) { - if (client->state != cs_spawned) + if (!(client->state == cs_spawned || (client->state == cs_connected && client->spawncount != svs.spawncount )) ) continue; ClientReliableWrite_Begin (host_client, svc_updateping, 4); @@ -1252,7 +1226,7 @@ void SV_Rate_f (void) return; } - rate = SV_BoundRate (atoi(Cmd_Argv(1))); + rate = SV_BoundRate (host_client->download != NULL, atoi(Cmd_Argv(1))); SV_ClientPrintf (host_client, PRINT_HIGH, "Net rate set to %i\n", rate); host_client->netchan.rate = 1.0/rate; @@ -1367,6 +1341,7 @@ void SV_NoSnap_f(void) } void SV_DemoList_f (void); +void SV_DemoInfo_f(void); typedef struct { @@ -1407,6 +1382,7 @@ ucmd_t ucmds[] = {"snap", SV_NoSnap_f}, {"stopdownload", SV_StopDownload_f}, {"demolist", SV_DemoList_f}, + {"demoinfo", SV_DemoInfo_f}, {NULL, NULL} }; @@ -1808,11 +1784,24 @@ void SV_ExecuteClientMessage (client_t *cl) int checksumIndex; byte checksum, calculatedChecksum; int seq_hash; + extern cvar_t sv_minping; // calc ping time frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; frame->ping_time = realtime - frame->senttime; + if (frame->ping_time*1000 > sv_minping.value) { + cl->delay -= 0.001;//0.5*(frame->ping_time - sv_minping.value*0.001); + if (cl->delay < 0) + cl->delay = 0; + } else if (frame->ping_time*1000 < sv_minping.value) { + cl->delay += 0.001;//-0.5*(frame->ping_time - sv_minping.value*0.001); + if (cl->delay > 300) + cl->delay = 300; + } + + + // make sure the reply sequence number matches the incoming // sequence number if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence) @@ -1873,6 +1862,13 @@ void SV_ExecuteClientMessage (client_t *cl) // read loss percentage cl->lossage = MSG_ReadByte(); + if (cl->state < cs_spawned && cl->download != NULL) { + if (cl->downloadsize) + cl->lossage = cl->downloadcount*100/cl->downloadsize; + else + cl->lossage = 100; + } + MSG_ReadDeltaUsercmd (&nullcmd, &oldest); MSG_ReadDeltaUsercmd (&oldest, &oldcmd); MSG_ReadDeltaUsercmd (&oldcmd, &newcmd); diff --git a/source/version.h b/source/version.h index cfadb38e..a2d27b76 100644 --- a/source/version.h +++ b/source/version.h @@ -2,8 +2,8 @@ #define GLQUAKE_VERSION 1.00 #define QW_VERSION 2.40 -#define QWE_VERSION "0.158 Beta" -#define QWE_VERNUM 0.158 +#define QWE_VERSION "0.165 Beta" +#define QWE_VERNUM 0.165 #define LINUX_VERSION 0.98 #define RELEASE_VERSION