*/
#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)"};
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;
else
print = SV_ClientPrintf;
+ if (!sv.active)
+ return;
+
for (players = 0, j = 0;j < svs.maxclients;j++)
if (svs.clients[j].active)
players++;
}
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");
}
}
==================
*/
+void Host_Pings_f (void); // called by Host_Ping_f
void Host_Ping_f (void)
{
int i;
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;
else
print = SV_ClientPrintf;
+ if (!sv.active)
+ return;
+
print("Client ping times:\n");
for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
{
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();
}
/*
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)
{
cls.demorecording = true;
}
+#endif
}
/*
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");
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");
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);
}
// version
- COM_ParseToken(&t, false);
+ COM_ParseTokenConsole(&t);
version = atoi(com_token);
if (version != SAVEGAME_VERSION)
{
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;
{
// 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] == '{')
for(;;)
{
oldt = t;
- COM_ParseToken(&t, false);
+ COM_ParseTokenConsole(&t);
if (com_token[0] == '{')
{
t = oldt;
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;
{
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);
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);
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;
}
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);
return;
}
+ Curl_SendRequirements();
+
host_client->spawned = true;
}
if (Cmd_Argc() > 2)
{
message = Cmd_Args();
- COM_ParseToken(&message, false);
+ COM_ParseTokenConsole(&message);
if (byNumber)
{
message++; // skip the #
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));
to = cls.netcon->peeraddress;
else
{
- if (!rcon_address.integer || !rcon_address.string[0])
+ if (!rcon_address.string[0])
{
Con_Printf ("You must either be connected, or set the rcon_address cvar to issue rcon commands\n");
return;
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));
+ }
+}
+
//=============================================================================
/*
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);