X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=host_cmd.c;h=408592e28301ca4af00558e7ff5aef3d2c07d57c;hb=cd7454f9df6b152a24c5a28750041d27023fbc1f;hp=bf993d67d799bf3f237f5f72c8bd9a86d1eaa523;hpb=06d35978246a4b7d5853809c149641a246aa4a36;p=xonotic%2Fdarkplaces.git diff --git a/host_cmd.c b/host_cmd.c index bf993d67..408592e2 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -19,10 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "libcurl.h" int current_skill; cvar_t sv_cheats = {0, "sv_cheats", "0", "enables cheat commands in any game, and cheat impulses in dpmod"}; -cvar_t rcon_password = {0, "rcon_password", "", "password to authenticate rcon commands"}; +cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands"}; cvar_t rcon_address = {0, "rcon_address", "", "server address to send rcon commands to (when not connected to a server)"}; cvar_t team = {CVAR_USERINFO | CVAR_SAVE, "team", "none", "QW team (4 character limit, example: blue)"}; cvar_t skin = {CVAR_USERINFO | CVAR_SAVE, "skin", "", "QW player skin name (example: base)"}; @@ -54,7 +55,8 @@ void Host_Status_f (void) if (cmd_source == src_command) { - if (!sv.active) + // if running a client, try to send over network so the client's status report parser will see the report + if (cls.state == ca_connected) { Cmd_ForwardToServer (); return; @@ -64,6 +66,9 @@ void Host_Status_f (void) else print = SV_ClientPrintf; + if (!sv.active) + return; + for (players = 0, j = 0;j < svs.maxclients;j++) if (svs.clients[j].active) players++; @@ -87,7 +92,7 @@ void Host_Status_f (void) } else hours = 0; - print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->fields.server->frags, hours, minutes, seconds); + print ("#%-3u %-16.16s %3i %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->fields.server->frags, hours, minutes, seconds); print (" %s\n", client->netconnection ? client->netconnection->address : "botclient"); } } @@ -212,6 +217,7 @@ Host_Ping_f ================== */ +void Host_Pings_f (void); // called by Host_Ping_f void Host_Ping_f (void) { int i; @@ -220,7 +226,8 @@ void Host_Ping_f (void) if (cmd_source == src_command) { - if (!sv.active) + // if running a client, try to send over network so the client's ping report parser will see the report + if (cls.state == ca_connected) { Cmd_ForwardToServer (); return; @@ -230,6 +237,9 @@ void Host_Ping_f (void) else print = SV_ClientPrintf; + if (!sv.active) + return; + print("Client ping times:\n"); for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) { @@ -237,6 +247,9 @@ void Host_Ping_f (void) continue; print("%4i %s\n", (int)floor(client->ping*1000+0.5), client->name); } + + // now call the Pings command also, which will send a report that contains packet loss for the scoreboard (as well as a simpler ping report) + Host_Pings_f(); } /* @@ -279,11 +292,12 @@ void Host_Map_f (void) svs.serverflags = 0; // haven't completed an episode yet allowcheats = sv_cheats.integer != 0; - strcpy(level, Cmd_Argv(1)); + strlcpy(level, Cmd_Argv(1), sizeof(level)); SV_SpawnServer(level); if (sv.active && cls.state == ca_disconnected) CL_EstablishConnection("local:1"); +#ifdef AUTODEMO_BROKEN // if cl_autodemo is set, automatically start recording a demo if one isn't being recorded already if (cl_autodemo.integer && !cls.demorecording) { @@ -304,6 +318,7 @@ void Host_Map_f (void) cls.demorecording = true; } +#endif } /* @@ -337,7 +352,7 @@ void Host_Changelevel_f (void) SV_SaveSpawnparms (); SV_VM_End(); allowcheats = sv_cheats.integer != 0; - strcpy(level, Cmd_Argv(1)); + strlcpy(level, Cmd_Argv(1), sizeof(level)); SV_SpawnServer(level); if (sv.active && cls.state == ca_disconnected) CL_EstablishConnection("local:1"); @@ -371,7 +386,7 @@ void Host_Restart_f (void) key_dest = key_game; allowcheats = sv_cheats.integer != 0; - strcpy(mapname, sv.name); + strlcpy(mapname, sv.name, sizeof(mapname)); SV_SpawnServer(mapname); if (sv.active && cls.state == ca_disconnected) CL_EstablishConnection("local:1"); @@ -613,7 +628,7 @@ void Host_Loadgame_f (void) return; } - strcpy (filename, Cmd_Argv(1)); + strlcpy (filename, Cmd_Argv(1), sizeof(filename)); FS_DefaultExtension (filename, ".sav", sizeof (filename)); Con_Printf("Loading game from %s...\n", filename); @@ -628,7 +643,7 @@ void Host_Loadgame_f (void) } // version - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); version = atoi(com_token); if (version != SAVEGAME_VERSION) { @@ -644,21 +659,21 @@ void Host_Loadgame_f (void) for (i = 0;i < NUM_SPAWN_PARMS;i++) { - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); spawn_parms[i] = atof(com_token); } // skill - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); // this silliness is so we can load 1.06 save files, which have float skill values current_skill = (int)(atof(com_token) + 0.5); Cvar_SetValue ("skill", (float)current_skill); // mapname - COM_ParseToken(&t, false); - strcpy (mapname, com_token); + COM_ParseTokenConsole(&t); + strlcpy (mapname, com_token, sizeof(mapname)); // time - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); time = atof(com_token); allowcheats = sv_cheats.integer != 0; @@ -679,7 +694,7 @@ void Host_Loadgame_f (void) { // light style oldt = t; - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); // if this is a 64 lightstyle savegame produced by Quake, stop now // we have to check this because darkplaces saves 256 lightstyle savegames if (com_token[0] == '{') @@ -697,7 +712,7 @@ void Host_Loadgame_f (void) for(;;) { oldt = t; - COM_ParseToken(&t, false); + COM_ParseTokenConsole(&t); if (com_token[0] == '{') { t = oldt; @@ -712,10 +727,10 @@ void Host_Loadgame_f (void) for (;;) { start = t; - while (COM_ParseToken(&t, false)) + while (COM_ParseTokenConsole(&t)) if (!strcmp(com_token, "}")) break; - if (!COM_ParseToken(&start, false)) + if (!COM_ParseTokenConsole(&start)) { // end of file break; @@ -820,7 +835,7 @@ void Host_Name_f (void) { if (host_client->spawned) SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name); - strcpy(host_client->old_name, host_client->name); + strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name)); // send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatename); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); @@ -879,7 +894,7 @@ void Host_Playermodel_f (void) PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(host_client->playermodel); if (strcmp(host_client->old_model, host_client->playermodel)) { - strcpy(host_client->old_model, host_client->playermodel); + strlcpy(host_client->old_model, host_client->playermodel, sizeof(host_client->old_model)); /*// send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatepmodel); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); @@ -917,7 +932,7 @@ void Host_Playerskin_f (void) if (cmd_source == src_command) { Cvar_Set ("_cl_playerskin", newPath); - CL_SetInfo("playermodel", newPath, true, false, false, false); + CL_SetInfo("playerskin", newPath, true, false, false, false); return; } @@ -937,9 +952,9 @@ void Host_Playerskin_f (void) PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playerskin)->string = PRVM_SetEngineString(host_client->playerskin); if (strcmp(host_client->old_skin, host_client->playerskin)) { - if (host_client->spawned) - SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin); - strcpy(host_client->old_skin, host_client->playerskin); + //if (host_client->spawned) + // SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin); + strlcpy(host_client->old_skin, host_client->playerskin, sizeof(host_client->old_skin)); /*// send notification to all clients MSG_WriteByte (&sv.reliable_datagram, svc_updatepskin); MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients); @@ -1513,6 +1528,8 @@ void Host_Begin_f (void) return; } + Curl_SendRequirements(); + host_client->spawned = true; } @@ -1577,7 +1594,7 @@ void Host_Kick_f (void) if (Cmd_Argc() > 2) { message = Cmd_Args(); - COM_ParseToken(&message, false); + COM_ParseTokenConsole(&message); if (byNumber) { message++; // skip the # @@ -1987,7 +2004,7 @@ void Host_SendCvar_f (void) if(Cmd_Argc() != 2) return; - if(!(c = Cvar_FindVar(Cmd_Argv(1)))) + if(!(c = Cvar_FindVar(Cmd_Argv(1))) || (c->flags & CVAR_PRIVATE)) return; if (cls.state != ca_dedicated) Cmd_ForwardStringToServer(va("sentcvar %s %s\n", c->name, c->string)); @@ -2319,6 +2336,71 @@ void Host_Packet_f (void) // credit: taken from QuakeWorld NetConn_Write(mysocket, send, out - send, &address); } +/* +==================== +Host_Pings_f + +Send back ping and packet loss update for all current players to this player +==================== +*/ +void Host_Pings_f (void) +{ + int i, j, ping, packetloss; + char temp[128]; + + if (cmd_source == src_command) + { + Cmd_ForwardToServer (); + return; + } + if (!host_client->netconnection) + return; + + if (sv.protocol != PROTOCOL_QUAKEWORLD) + { + MSG_WriteByte(&host_client->netconnection->message, svc_stufftext); + MSG_WriteUnterminatedString(&host_client->netconnection->message, "pingplreport"); + } + for (i = 0;i < svs.maxclients;i++) + { + packetloss = 0; + if (svs.clients[i].netconnection) + for (j = 0;j < 100;j++) + packetloss += svs.clients[i].netconnection->packetlost[j]; + ping = (int)floor(svs.clients[i].ping*1000+0.5); + ping = bound(0, ping, 9999); + if (sv.protocol == PROTOCOL_QUAKEWORLD) + { + // send qw_svc_updateping and qw_svc_updatepl messages + MSG_WriteByte(&host_client->netconnection->message, qw_svc_updateping); + MSG_WriteShort(&host_client->netconnection->message, ping); + MSG_WriteByte(&host_client->netconnection->message, qw_svc_updatepl); + MSG_WriteByte(&host_client->netconnection->message, packetloss); + } + else + { + // write the string into the packet as multiple unterminated strings to avoid needing a local buffer + dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss); + MSG_WriteUnterminatedString(&host_client->netconnection->message, temp); + } + } + if (sv.protocol != PROTOCOL_QUAKEWORLD) + MSG_WriteString(&host_client->netconnection->message, "\n"); +} + +void Host_PingPLReport_f(void) +{ + int i; + int l = Cmd_Argc(); + if (l > cl.maxclients) + l = cl.maxclients; + for (i = 0;i < l;i++) + { + cl.scores[i].qw_ping = atoi(Cmd_Argv(1+i*2)); + cl.scores[i].qw_packetloss = atoi(Cmd_Argv(1+i*2+1)); + } +} + //============================================================================= /* @@ -2410,6 +2492,9 @@ void Host_InitCommands (void) Cmd_AddCommand ("topcolor", Host_TopColor_f, "QW command to set top color without changing bottom color"); Cmd_AddCommand ("bottomcolor", Host_BottomColor_f, "QW command to set bottom color without changing top color"); + Cmd_AddCommand ("pings", Host_Pings_f, "command sent by clients to request updated ping and packetloss of players on scoreboard (originally from QW, but also used on NQ servers)"); + Cmd_AddCommand ("pingplreport", Host_PingPLReport_f, "command sent by server containing client ping and packet loss values for scoreboard, triggered by pings command from client (not used by QW servers)"); + Cvar_RegisterVariable (&team); Cvar_RegisterVariable (&skin); Cvar_RegisterVariable (&noaim);