#include "sv_demo.h"
#include "image.h"
+#include "utf8lib.h"
+
// for secure rcon authentication
#include "hmac.h"
#include "mdfour.h"
cvar_t sv_adminnick = {CVAR_SAVE, "sv_adminnick", "", "nick name to use for admin messages instead of host name"};
cvar_t sv_status_privacy = {CVAR_SAVE, "sv_status_privacy", "0", "do not show IP addresses in 'status' replies to clients"};
cvar_t sv_status_show_qcstatus = {CVAR_SAVE, "sv_status_show_qcstatus", "0", "show the 'qcstatus' field in status replies, not the 'frags' field. Turn this on if your mod uses this field, and the 'frags' field on the other hand has no meaningful value."};
-cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
-cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
+cvar_t sv_namechangetimer = {CVAR_SAVE, "sv_namechangetimer", "5", "how often to allow name changes, in seconds (prevents people from using animated names and other tricks"};
+cvar_t rcon_password = {CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password; may be set to a string of the form user1:pass1 user2:pass2 user3:pass3 to allow multiple user accounts - the client then has to specify ONE of these combinations"};
+cvar_t rcon_secure = {CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
+cvar_t rcon_secure_challengetimeout = {0, "rcon_secure_challengetimeout", "5", "challenge-based secure rcon: time out requests if no challenge came within this time interval"};
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)"};
Host_Status_f
==================
*/
-void Host_Status_f (void)
+static void Host_Status_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char qcstatus[256];
client_t *client;
int seconds = 0, minutes = 0, hours = 0, i, j, k, in, players, ping = 0, packetloss = 0;
void (*print) (const char *fmt, ...);
- char ip[22];
+ char ip[48]; // can contain a full length v6 address with [] and a port
int frags;
+ char vabuf[1024];
if (cmd_source == src_command)
{
if (!sv.active)
return;
-
- if(cmd_source == src_command)
- SV_VM_Begin();
-
+
in = 0;
if (Cmd_Argc() == 2)
{
print ("version: %s build %s\n", gamename, buildstring);
print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol));
print ("map: %s\n", sv.name);
- print ("timing: %s\n", Host_TimingReport());
+ print ("timing: %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
print ("players: %i active (%i max)\n\n", players, svs.maxclients);
if (in == 1)
- print ("^2IP %%pl ping time frags no name\n");
+ print ("^2IP %%pl ping time frags no name\n");
else if (in == 2)
- print ("^5IP no name\n");
+ print ("^5IP no name\n");
for (i = 0, k = 0, client = svs.clients;i < svs.maxclients;i++, client++)
{
packetloss = 0;
if (client->netconnection)
for (j = 0;j < NETGRAPH_PACKETS;j++)
- if (client->netconnection->incoming_unreliablesize[j] == NETGRAPH_LOSTPACKET)
+ if (client->netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
packetloss++;
- packetloss = packetloss * 100 / NETGRAPH_PACKETS;
+ packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
ping = bound(0, (int)floor(client->ping*1000+0.5), 9999);
}
if(sv_status_privacy.integer && cmd_source != src_command)
- strlcpy(ip, client->netconnection ? "hidden" : "botclient" , 22);
+ strlcpy(ip, client->netconnection ? "hidden" : "botclient", 48);
else
- strlcpy(ip, (client->netconnection && client->netconnection->address) ? client->netconnection->address : "botclient", 22);
+ strlcpy(ip, (client->netconnection && client->netconnection->address) ? client->netconnection->address : "botclient", 48);
frags = client->frags;
- if(sv_status_show_qcstatus.integer && prog->fieldoffsets.clientstatus >= 0)
+ if(sv_status_show_qcstatus.integer)
{
- const char *str = PRVM_E_STRING(PRVM_EDICT_NUM(i + 1), prog->fieldoffsets.clientstatus);
+ prvm_edict_t *ed = PRVM_EDICT_NUM(i + 1);
+ const char *str = PRVM_GetString(prog, PRVM_serveredictstring(ed, clientstatus));
if(str && *str)
{
char *p;
if (in == 0) // default layout
{
- print ("#%-3u ", i+1);
- print ("%-16.16s ", client->name);
- print ("%4i ", frags);
- print ("%2i:%02i:%02i\n ", hours, minutes, seconds);
- print ("%s\n", ip);
+ if (sv.protocol == PROTOCOL_QUAKE && svs.maxclients <= 99)
+ {
+ // LordHavoc: this is very touchy because we must maintain ProQuake compatible status output
+ print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", i+1, client->name, frags, hours, minutes, seconds);
+ print (" %s\n", ip);
+ }
+ else
+ {
+ // LordHavoc: no real restrictions here, not a ProQuake-compatible protocol anyway...
+ print ("#%-3u %-16.16s %4i %2i:%02i:%02i\n", i+1, client->name, frags, hours, minutes, seconds);
+ print (" %s\n", ip);
+ }
}
else if (in == 1) // extended layout
{
- k%2 ? print("^3") : print("^7");
- print ("%-21s ", ip);
- print ("%2i ", packetloss);
- print ("%4i ", ping);
- print ("%2i:%02i:%02i ", hours, minutes, seconds);
- print ("%4i ", frags);
- print ("#%-3u ", i+1);
- print ("^7%s\n", client->name);
+ print ("%s%-47s %2i %4i %2i:%02i:%02i %4i #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, packetloss, ping, hours, minutes, seconds, frags, i+1, client->name);
}
else if (in == 2) // reduced layout
{
- k%2 ? print("^3") : print("^7");
- print ("%-21s ", ip);
- print ("#%-3u ", i+1);
- print ("^7%s\n", client->name);
+ print ("%s%-47s #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, i+1, client->name);
}
}
-
- if(cmd_source == src_command)
- SV_VM_End();
}
Sets client to godmode
==================
*/
-void Host_God_f (void)
+static void Host_God_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
return;
}
- host_client->edict->fields.server->flags = (int)host_client->edict->fields.server->flags ^ FL_GODMODE;
- if (!((int)host_client->edict->fields.server->flags & FL_GODMODE) )
+ PRVM_serveredictfloat(host_client->edict, flags) = (int)PRVM_serveredictfloat(host_client->edict, flags) ^ FL_GODMODE;
+ if (!((int)PRVM_serveredictfloat(host_client->edict, flags) & FL_GODMODE) )
SV_ClientPrint("godmode OFF\n");
else
SV_ClientPrint("godmode ON\n");
}
-void Host_Notarget_f (void)
+static void Host_Notarget_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
return;
}
- host_client->edict->fields.server->flags = (int)host_client->edict->fields.server->flags ^ FL_NOTARGET;
- if (!((int)host_client->edict->fields.server->flags & FL_NOTARGET) )
+ PRVM_serveredictfloat(host_client->edict, flags) = (int)PRVM_serveredictfloat(host_client->edict, flags) ^ FL_NOTARGET;
+ if (!((int)PRVM_serveredictfloat(host_client->edict, flags) & FL_NOTARGET) )
SV_ClientPrint("notarget OFF\n");
else
SV_ClientPrint("notarget ON\n");
qboolean noclip_anglehack;
-void Host_Noclip_f (void)
+static void Host_Noclip_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
return;
}
- if (host_client->edict->fields.server->movetype != MOVETYPE_NOCLIP)
+ if (PRVM_serveredictfloat(host_client->edict, movetype) != MOVETYPE_NOCLIP)
{
noclip_anglehack = true;
- host_client->edict->fields.server->movetype = MOVETYPE_NOCLIP;
+ PRVM_serveredictfloat(host_client->edict, movetype) = MOVETYPE_NOCLIP;
SV_ClientPrint("noclip ON\n");
}
else
{
noclip_anglehack = false;
- host_client->edict->fields.server->movetype = MOVETYPE_WALK;
+ PRVM_serveredictfloat(host_client->edict, movetype) = MOVETYPE_WALK;
SV_ClientPrint("noclip OFF\n");
}
}
Sets client to flymode
==================
*/
-void Host_Fly_f (void)
+static void Host_Fly_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
if (!allowcheats)
{
SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
return;
}
- if (host_client->edict->fields.server->movetype != MOVETYPE_FLY)
+ if (PRVM_serveredictfloat(host_client->edict, movetype) != MOVETYPE_FLY)
{
- host_client->edict->fields.server->movetype = MOVETYPE_FLY;
+ PRVM_serveredictfloat(host_client->edict, movetype) = MOVETYPE_FLY;
SV_ClientPrint("flymode ON\n");
}
else
{
- host_client->edict->fields.server->movetype = MOVETYPE_WALK;
+ PRVM_serveredictfloat(host_client->edict, movetype) = MOVETYPE_WALK;
SV_ClientPrint("flymode OFF\n");
}
}
==================
*/
void Host_Pings_f (void); // called by Host_Ping_f
-void Host_Ping_f (void)
+static void Host_Ping_f (void)
{
int i;
client_t *client;
command from the console. Active clients are kicked off.
======================
*/
-void Host_Map_f (void)
+static void Host_Map_f (void)
{
char level[MAX_QPATH];
}
// remove menu
+ if (key_dest == key_menu || key_dest == key_menu_grabbed)
+ MR_ToggleMenu(0);
key_dest = key_game;
svs.serverflags = 0; // haven't completed an episode yet
strlcpy(level, Cmd_Argv(1), sizeof(level));
SV_SpawnServer(level);
if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1");
+ CL_EstablishConnection("local:1", -2);
}
/*
Goes to a new map, taking all clients along
==================
*/
-void Host_Changelevel_f (void)
+static void Host_Changelevel_f (void)
{
char level[MAX_QPATH];
}
// remove menu
+ if (key_dest == key_menu || key_dest == key_menu_grabbed)
+ MR_ToggleMenu(0);
key_dest = key_game;
- SV_VM_Begin();
SV_SaveSpawnparms ();
- SV_VM_End();
allowcheats = sv_cheats.integer != 0;
strlcpy(level, Cmd_Argv(1), sizeof(level));
SV_SpawnServer(level);
if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1");
+ CL_EstablishConnection("local:1", -2);
}
/*
Restarts the current server for a dead player
==================
*/
-void Host_Restart_f (void)
+static void Host_Restart_f (void)
{
char mapname[MAX_QPATH];
}
// remove menu
+ if (key_dest == key_menu || key_dest == key_menu_grabbed)
+ MR_ToggleMenu(0);
key_dest = key_game;
allowcheats = sv_cheats.integer != 0;
strlcpy(mapname, sv.name, sizeof(mapname));
SV_SpawnServer(mapname);
if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1");
+ CL_EstablishConnection("local:1", -2);
}
/*
// will still contain its IP address, so get the address...
InfoString_GetValue(cls.userinfo, "*ip", temp, sizeof(temp));
if (temp[0])
- CL_EstablishConnection(temp);
+ CL_EstablishConnection(temp, -1);
else
Con_Printf("Reconnect to what server? (you have not connected to a server yet)\n");
return;
User command to connect to server
=====================
*/
-void Host_Connect_f (void)
+static void Host_Connect_f (void)
{
- if (Cmd_Argc() != 2)
+ if (Cmd_Argc() < 2)
{
- Con_Print("connect <serveraddress> : connect to a multiplayer game\n");
+ Con_Print("connect <serveraddress> [<key> <value> ...]: connect to a multiplayer game\n");
return;
}
// clear the rcon password, to prevent vulnerability by stuffcmd-ing a connect command
- if(!rcon_secure.integer)
+ if(rcon_secure.integer <= 0)
Cvar_SetQuick(&rcon_password, "");
- CL_EstablishConnection(Cmd_Argv(1));
+ CL_EstablishConnection(Cmd_Argv(1), 2);
}
#define SAVEGAME_VERSION 5
-void Host_Savegame_to (const char *name)
+void Host_Savegame_to(prvm_prog_t *prog, const char *name)
{
qfile_t *f;
- int i, lightstyles = 64;
+ int i, k, l, numbuffers, lightstyles = 64;
char comment[SAVEGAME_COMMENT_LENGTH+1];
+ char line[MAX_INPUTLINE];
qboolean isserver;
+ char *s;
// first we have to figure out if this can be saved in 64 lightstyles
// (for Quake compatibility)
if (sv.lightstyles[i][0])
lightstyles = i+1;
- isserver = !strcmp(PRVM_NAME, "server");
+ isserver = prog == SVVM_prog;
Con_Printf("Saving game to %s...\n", name);
f = FS_OpenRealFile(name, "wb", false);
memset(comment, 0, sizeof(comment));
if(isserver)
- dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(prog->edicts->fields.server->message), (int)prog->globals.server->killed_monsters, (int)prog->globals.server->total_monsters);
+ dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
else
- dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", PRVM_NAME);
+ dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", prog->name);
// convert space to _ to make stdio happy
// LordHavoc: convert control characters to _ as well
for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
FS_Print(f,"m\n");
}
- PRVM_ED_WriteGlobals (f);
+ PRVM_ED_WriteGlobals (prog, f);
for (i=0 ; i<prog->num_edicts ; i++)
{
FS_Printf(f,"// edict %d\n", i);
//Con_Printf("edict %d...\n", i);
- PRVM_ED_Write (f, PRVM_EDICT_NUM(i));
+ PRVM_ED_Write (prog, f, PRVM_EDICT_NUM(i));
}
#if 1
for (i=1 ; i<MAX_SOUNDS ; i++)
if (sv.sound_precache[i][0])
FS_Printf(f,"sv.sound_precache %i %s\n", i, sv.sound_precache[i]);
+
+ // darkplaces extension - save buffers
+ numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+ for (i = 0; i < numbuffers; i++)
+ {
+ prvm_stringbuffer_t *stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
+ if(stringbuffer && (stringbuffer->flags & STRINGBUFFER_SAVED))
+ {
+ FS_Printf(f,"sv.buffer %i %i \"string\"\n", i, stringbuffer->flags & STRINGBUFFER_QCFLAGS);
+ for(k = 0; k < stringbuffer->num_strings; k++)
+ {
+ if (!stringbuffer->strings[k])
+ continue;
+ // Parse the string a bit to turn special characters
+ // (like newline, specifically) into escape codes
+ s = stringbuffer->strings[k];
+ for (l = 0;l < (int)sizeof(line) - 2 && *s;)
+ {
+ if (*s == '\n')
+ {
+ line[l++] = '\\';
+ line[l++] = 'n';
+ }
+ else if (*s == '\r')
+ {
+ line[l++] = '\\';
+ line[l++] = 'r';
+ }
+ else if (*s == '\\')
+ {
+ line[l++] = '\\';
+ line[l++] = '\\';
+ }
+ else if (*s == '"')
+ {
+ line[l++] = '\\';
+ line[l++] = '"';
+ }
+ else
+ line[l++] = *s;
+ s++;
+ }
+ line[l] = '\0';
+ FS_Printf(f,"sv.bufstr %i %i \"%s\"\n", i, k, line);
+ }
+ }
+ }
FS_Printf(f,"*/\n");
#endif
Host_Savegame_f
===============
*/
-void Host_Savegame_f (void)
+static void Host_Savegame_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char name[MAX_QPATH];
+ qboolean deadflag = false;
if (!sv.active)
{
return;
}
+ deadflag = cl.islocalgame && svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag);
+
if (cl.islocalgame)
{
// singleplayer checks
return;
}
- if (svs.clients[0].active && svs.clients[0].edict->fields.server->deadflag)
+ if (deadflag)
{
Con_Print("Can't savegame with a dead player\n");
return;
strlcpy (name, Cmd_Argv(1), sizeof (name));
FS_DefaultExtension (name, ".sav", sizeof (name));
- SV_VM_Begin();
- Host_Savegame_to(name);
- SV_VM_End();
+ Host_Savegame_to(prog, name);
}
Host_Loadgame_f
===============
*/
-void Host_Loadgame_f (void)
+
+prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format);
+void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str);
+void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer);
+void BufStr_Flush(prvm_prog_t *prog);
+
+static void Host_Loadgame_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
char filename[MAX_QPATH];
char mapname[MAX_QPATH];
float time;
const char *t;
char *text;
prvm_edict_t *ent;
- int i;
+ int i, k, numbuffers;
int entnum;
int version;
float spawn_parms[NUM_SPAWN_PARMS];
+ prvm_stringbuffer_t *stringbuffer;
if (Cmd_Argc() != 2)
{
CL_Disconnect ();
// remove menu
+ if (key_dest == key_menu || key_dest == key_menu_grabbed)
+ MR_ToggleMenu(0);
key_dest = key_game;
cls.demonum = -1; // stop demo loop in case this fails
Con_Printf("Host_Loadgame_f: loading version\n");
// version
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
version = atoi(com_token);
if (version != SAVEGAME_VERSION)
{
Con_Printf("Host_Loadgame_f: loading description\n");
// description
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
for (i = 0;i < NUM_SPAWN_PARMS;i++)
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
spawn_parms[i] = atof(com_token);
}
// skill
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
// 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);
Con_Printf("Host_Loadgame_f: loading mapname\n");
// mapname
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
strlcpy (mapname, com_token, sizeof(mapname));
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: loading time\n");
// time
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
time = atof(com_token);
allowcheats = sv_cheats.integer != 0;
// load the light styles
- SV_VM_Begin();
// -1 is the globals
entnum = -1;
{
// light style
start = t;
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
// if this is a 64 lightstyle savegame produced by Quake, stop now
// we have to check this because darkplaces may save more than 64
if (com_token[0] == '{')
for (;;)
{
start = t;
- if (!COM_ParseToken_Simple(&t, false, false))
+ if (!COM_ParseToken_Simple(&t, false, false, true))
break;
if (com_token[0] == '{')
{
}
}
+ // unlink all entities
+ World_UnlinkAll(&sv.world);
+
// load the edicts out of the savegame file
end = t;
for (;;)
{
start = t;
- while (COM_ParseToken_Simple(&t, false, false))
+ while (COM_ParseToken_Simple(&t, false, false, true))
if (!strcmp(com_token, "}"))
break;
- if (!COM_ParseToken_Simple(&start, false, false))
+ if (!COM_ParseToken_Simple(&start, false, false, true))
{
// end of file
break;
Con_Printf("Host_Loadgame_f: loading globals\n");
// parse the global vars
- PRVM_ED_ParseGlobals (start);
+ PRVM_ED_ParseGlobals (prog, start);
+
+ // restore the autocvar globals
+ Cvar_UpdateAllAutoCvars();
}
else
{
Host_Error("Host_PerformLoadGame: too many edicts in save file (reached MAX_EDICTS %i)", MAX_EDICTS);
}
while (entnum >= prog->max_edicts)
- PRVM_MEM_IncreaseEdicts();
+ PRVM_MEM_IncreaseEdicts(prog);
ent = PRVM_EDICT_NUM(entnum);
- memset (ent->fields.server, 0, prog->progs->entityfields * 4);
+ memset(ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
ent->priv.server->free = false;
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: loading edict %d\n", entnum);
- PRVM_ED_ParseEdict (start, ent);
+ PRVM_ED_ParseEdict (prog, start, ent);
// link it into the bsp tree
if (!ent->priv.server->free)
- SV_LinkEdict (ent, false);
+ SV_LinkEdict(ent);
}
end = t;
memset(sv.lightstyles[0], 0, sizeof(sv.lightstyles));
memset(sv.model_precache[0], 0, sizeof(sv.model_precache));
memset(sv.sound_precache[0], 0, sizeof(sv.sound_precache));
- while (COM_ParseToken_Simple(&t, false, false))
+ BufStr_Flush(prog);
+
+ while (COM_ParseToken_Simple(&t, false, false, true))
{
if (!strcmp(com_token, "sv.lightstyles"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_LIGHTSTYLES)
strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
else
}
else if (!strcmp(com_token, "sv.model_precache"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_MODELS)
{
strlcpy(sv.model_precache[i], com_token, sizeof(sv.model_precache[i]));
- sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, sv.model_precache[i][0] == '*' ? sv.modelname : NULL);
+ sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, sv.model_precache[i][0] == '*' ? sv.worldname : NULL);
}
else
Con_Printf("unsupported model %i \"%s\"\n", i, com_token);
}
else if (!strcmp(com_token, "sv.sound_precache"))
{
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false);
+ COM_ParseToken_Simple(&t, false, false, true);
if (i >= 0 && i < MAX_SOUNDS)
strlcpy(sv.sound_precache[i], com_token, sizeof(sv.sound_precache[i]));
else
Con_Printf("unsupported sound %i \"%s\"\n", i, com_token);
}
+ else if (!strcmp(com_token, "sv.buffer"))
+ {
+ if (COM_ParseToken_Simple(&t, false, false, true))
+ {
+ i = atoi(com_token);
+ if (i >= 0)
+ {
+ k = STRINGBUFFER_SAVED;
+ if (COM_ParseToken_Simple(&t, false, false, true))
+ k |= atoi(com_token);
+ if (!BufStr_FindCreateReplace(prog, i, k, "string"))
+ Con_Printf("failed to create stringbuffer %i\n", i);
+ }
+ else
+ Con_Printf("unsupported stringbuffer index %i \"%s\"\n", i, com_token);
+ }
+ else
+ Con_Printf("unexpected end of line when parsing sv.buffer (expected buffer index)\n");
+ }
+ else if (!strcmp(com_token, "sv.bufstr"))
+ {
+ if (!COM_ParseToken_Simple(&t, false, false, true))
+ Con_Printf("unexpected end of line when parsing sv.bufstr\n");
+ else
+ {
+ i = atoi(com_token);
+ stringbuffer = BufStr_FindCreateReplace(prog, i, STRINGBUFFER_SAVED, "string");
+ if (stringbuffer)
+ {
+ if (COM_ParseToken_Simple(&t, false, false, true))
+ {
+ k = atoi(com_token);
+ if (COM_ParseToken_Simple(&t, false, false, true))
+ BufStr_Set(prog, stringbuffer, k, com_token);
+ else
+ Con_Printf("unexpected end of line when parsing sv.bufstr (expected string)\n");
+ }
+ else
+ Con_Printf("unexpected end of line when parsing sv.bufstr (expected strindex)\n");
+ }
+ else
+ Con_Printf("failed to create stringbuffer %i \"%s\"\n", i, com_token);
+ }
+ }
// skip any trailing text or unrecognized commands
- while (COM_ParseToken_Simple(&t, true, false) && strcmp(com_token, "\n"))
+ while (COM_ParseToken_Simple(&t, true, false, true) && strcmp(com_token, "\n"))
;
}
}
}
Mem_Free(text);
+ // remove all temporary flagged string buffers (ones created with BufStr_FindCreateReplace)
+ numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+ for (i = 0; i < numbuffers; i++)
+ {
+ if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) )
+ if (stringbuffer->flags & STRINGBUFFER_TEMP)
+ BufStr_Del(prog, stringbuffer);
+ }
+
if(developer_entityparsing.integer)
Con_Printf("Host_Loadgame_f: finished\n");
- SV_VM_End();
-
// make sure we're connected to loopback
if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1");
+ CL_EstablishConnection("local:1", -2);
}
//============================================================================
======================
*/
cvar_t cl_name = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_name", "player", "internal storage cvar for current player name (changed by name command)"};
-void Host_Name_f (void)
+static void Host_Name_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
qboolean valid_colors;
const char *newNameSource;
if (realtime < host_client->nametime)
{
- SV_ClientPrintf("You can't change name more than once every 5 seconds!\n");
+ SV_ClientPrintf("You can't change name more than once every %.1f seconds!\n", max(0.0f, sv_namechangetimer.value));
return;
}
- host_client->nametime = realtime + 5;
+ host_client->nametime = realtime + max(0.0f, sv_namechangetimer.value);
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->name, newName, sizeof (host_client->name));
host_client->name[1] = '0' + STRING_COLOR_DEFAULT;
}
- COM_StringLengthNoColors(host_client->name, 0, &valid_colors);
+ u8_COM_StringLengthNoColors(host_client->name, 0, &valid_colors);
if(!valid_colors) // NOTE: this also proves the string is not empty, as "" is a valid colored string
{
size_t l;
if (j >= 0 && strlen(host_client->name) < sizeof(host_client->name) - 2)
memcpy(host_client->name + strlen(host_client->name), STRING_COLOR_DEFAULT_STR, strlen(STRING_COLOR_DEFAULT_STR) + 1);
- host_client->edict->fields.server->netname = PRVM_SetEngineString(host_client->name);
+ PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
if (strcmp(host_client->old_name, host_client->name))
{
- if (host_client->spawned)
+ if (host_client->begun)
SV_BroadcastPrintf("%s ^7changed name to %s\n", 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
Host_Playermodel_f
======================
*/
-cvar_t cl_playermodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playermodel", "", "internal storage cvar for current player model in Nexuiz (changed by playermodel command)"};
+cvar_t cl_playermodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playermodel", "", "internal storage cvar for current player model in Nexuiz/Xonotic (changed by playermodel command)"};
// the old cl_playermodel in cl_main has been renamed to __cl_playermodel
-void Host_Playermodel_f (void)
+static void Host_Playermodel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
char newPath[sizeof(host_client->playermodel)];
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playermodel, newPath, sizeof (host_client->playermodel));
- if( prog->fieldoffsets.playermodel >= 0 )
- PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.playermodel)->string = PRVM_SetEngineString(host_client->playermodel);
+ PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
if (strcmp(host_client->old_model, host_client->playermodel))
{
strlcpy(host_client->old_model, host_client->playermodel, sizeof(host_client->old_model));
Host_Playerskin_f
======================
*/
-cvar_t cl_playerskin = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playerskin", "", "internal storage cvar for current player skin in Nexuiz (changed by playerskin command)"};
-void Host_Playerskin_f (void)
+cvar_t cl_playerskin = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playerskin", "", "internal storage cvar for current player skin in Nexuiz/Xonotic (changed by playerskin command)"};
+static void Host_Playerskin_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i, j;
char newPath[sizeof(host_client->playerskin)];
// point the string back at updateclient->name to keep it safe
strlcpy (host_client->playerskin, newPath, sizeof (host_client->playerskin));
- if( prog->fieldoffsets.playerskin >= 0 )
- PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.playerskin)->string = PRVM_SetEngineString(host_client->playerskin);
+ PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
if (strcmp(host_client->old_skin, host_client->playerskin))
{
- //if (host_client->spawned)
+ //if (host_client->begun)
// 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
}
}
-void Host_Version_f (void)
+static void Host_Version_f (void)
{
Con_Printf("Version: %s build %s\n", gamename, buildstring);
}
-void Host_Say(qboolean teamonly)
+static void Host_Say(qboolean teamonly)
{
+ prvm_prog_t *prog = SVVM_prog;
client_t *save;
int j, quoted;
const char *p1;
// note: save is not a valid edict if fromServer is true
save = host_client;
for (j = 0, host_client = svs.clients;j < svs.maxclients;j++, host_client++)
- if (host_client->active && (!teamonly || host_client->edict->fields.server->team == save->edict->fields.server->team))
+ if (host_client->active && (!teamonly || PRVM_serveredictfloat(host_client->edict, team) == PRVM_serveredictfloat(save->edict, team)))
SV_ClientPrint(text);
host_client = save;
}
-void Host_Say_f(void)
+static void Host_Say_f(void)
{
Host_Say(false);
}
-void Host_Say_Team_f(void)
+static void Host_Say_Team_f(void)
{
Host_Say(true);
}
-void Host_Tell_f(void)
+static void Host_Tell_f(void)
{
const char *playername_start = NULL;
size_t playername_length = 0;
==================
*/
cvar_t cl_color = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_color", "0", "internal storage cvar for current player colors (changed by color command)"};
-void Host_Color(int changetop, int changebottom)
+static void Host_Color(int changetop, int changebottom)
{
+ prvm_prog_t *prog = SVVM_prog;
int top, bottom, playercolor;
// get top and bottom either from the provided values or the current values
if (cls.protocol == PROTOCOL_QUAKEWORLD)
return;
- if (host_client->edict && prog->funcoffsets.SV_ChangeTeam)
+ if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
{
Con_DPrint("Calling SV_ChangeTeam\n");
- prog->globals.server->time = sv.time;
- prog->globals.generic[OFS_PARM0] = playercolor;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram(prog->funcoffsets.SV_ChangeTeam, "QC function SV_ChangeTeam is missing");
+ prog->globals.fp[OFS_PARM0] = playercolor;
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
}
else
{
- prvm_eval_t *val;
if (host_client->edict)
{
- if ((val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.clientcolors)))
- val->_float = playercolor;
- host_client->edict->fields.server->team = bottom + 1;
+ PRVM_serveredictfloat(host_client->edict, clientcolors) = playercolor;
+ PRVM_serveredictfloat(host_client->edict, team) = bottom + 1;
}
host_client->colors = playercolor;
if (host_client->old_colors != host_client->colors)
}
}
-void Host_Color_f(void)
+static void Host_Color_f(void)
{
int top, bottom;
Host_Color(top, bottom);
}
-void Host_TopColor_f(void)
+static void Host_TopColor_f(void)
{
if (Cmd_Argc() == 1)
{
Host_Color(atoi(Cmd_Argv(1)), -1);
}
-void Host_BottomColor_f(void)
+static void Host_BottomColor_f(void)
{
if (Cmd_Argc() == 1)
{
}
cvar_t cl_rate = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate", "20000", "internal storage cvar for current rate (changed by rate command)"};
-void Host_Rate_f(void)
+static void Host_Rate_f(void)
{
int rate;
Host_Kill_f
==================
*/
-void Host_Kill_f (void)
+static void Host_Kill_f (void)
{
- if (host_client->edict->fields.server->health <= 0)
+ prvm_prog_t *prog = SVVM_prog;
+ if (PRVM_serveredictfloat(host_client->edict, health) <= 0)
{
SV_ClientPrint("Can't suicide -- already dead!\n");
return;
}
- prog->globals.server->time = sv.time;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (prog->globals.server->ClientKill, "QC function ClientKill is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
}
Host_Pause_f
==================
*/
-void Host_Pause_f (void)
+static void Host_Pause_f (void)
{
- if (!pausable.integer)
- SV_ClientPrint("Pause not allowed.\n");
+ void (*print) (const char *fmt, ...);
+ if (cmd_source == src_command)
+ {
+ // if running a client, try to send over network so the pause is handled by the server
+ if (cls.state == ca_connected)
+ {
+ Cmd_ForwardToServer ();
+ return;
+ }
+ print = Con_Printf;
+ }
else
+ print = SV_ClientPrintf;
+
+ if (!pausable.integer)
{
- sv.paused ^= 1;
- SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
- // send notification to all clients
- MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
- MSG_WriteByte(&sv.reliable_datagram, sv.paused);
+ if (cmd_source == src_client)
+ {
+ if(cls.state == ca_dedicated || host_client != &svs.clients[0]) // non-admin
+ {
+ print("Pause not allowed.\n");
+ return;
+ }
+ }
}
+
+ sv.paused ^= 1;
+ SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
+ // send notification to all clients
+ MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
+ MSG_WriteByte(&sv.reliable_datagram, sv.paused);
}
/*
cvar_t cl_pmodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_pmodel", "0", "internal storage cvar for current player model number in nehahra (changed by pmodel command)"};
static void Host_PModel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
- prvm_eval_t *val;
if (Cmd_Argc () == 1)
{
return;
}
- if (host_client->edict && (val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.pmodel)))
- val->_float = i;
+ PRVM_serveredictfloat(host_client->edict, pmodel) = i;
}
//===========================================================================
Host_PreSpawn_f
==================
*/
-void Host_PreSpawn_f (void)
+static void Host_PreSpawn_f (void)
{
- if (host_client->spawned)
+ if (host_client->prespawned)
{
- Con_Print("prespawn not valid -- already spawned\n");
+ Con_Print("prespawn not valid -- already prespawned\n");
return;
}
+ host_client->prespawned = true;
if (host_client->netconnection)
{
Host_Spawn_f
==================
*/
-void Host_Spawn_f (void)
+static void Host_Spawn_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
int i;
client_t *client;
int stats[MAX_CL_STATS];
+ if (!host_client->prespawned)
+ {
+ Con_Print("Spawn not valid -- not yet prespawned\n");
+ return;
+ }
if (host_client->spawned)
{
Con_Print("Spawn not valid -- already spawned\n");
return;
}
+ host_client->spawned = true;
// reset name change timer again because they might want to change name
// again in the first 5 seconds after connecting
if (sv.loadgame)
{
// loaded games are fully initialized already
- if (prog->funcoffsets.RestoreGame)
+ if (PRVM_serverfunction(RestoreGame))
{
Con_DPrint("Calling RestoreGame\n");
- prog->globals.server->time = sv.time;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram(prog->funcoffsets.RestoreGame, "QC function RestoreGame is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
}
}
else
{
- //Con_Printf("Host_Spawn_f: host_client->edict->netname = %s, host_client->edict->netname = %s, host_client->name = %s\n", PRVM_GetString(host_client->edict->fields.server->netname), PRVM_GetString(host_client->edict->fields.server->netname), host_client->name);
+ //Con_Printf("Host_Spawn_f: host_client->edict->netname = %s, host_client->edict->netname = %s, host_client->name = %s\n", PRVM_GetString(PRVM_serveredictstring(host_client->edict, netname)), PRVM_GetString(PRVM_serveredictstring(host_client->edict, netname)), host_client->name);
// copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
- (&prog->globals.server->parm1)[i] = host_client->spawn_parms[i];
+ (&PRVM_serverglobalfloat(parm1))[i] = host_client->spawn_parms[i];
// call the spawn function
host_client->clientconnectcalled = true;
- prog->globals.server->time = sv.time;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict);
- PRVM_ExecuteProgram (prog->globals.server->ClientConnect, "QC function ClientConnect is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
+ prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
if (cls.state == ca_dedicated)
Con_Printf("%s connected\n", host_client->name);
- PRVM_ExecuteProgram (prog->globals.server->PutClientInServer, "QC function PutClientInServer is missing");
+ PRVM_serverglobalfloat(time) = sv.time;
+ prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
}
if (!host_client->netconnection)
// send some stats
MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALSECRETS);
- MSG_WriteLong (&host_client->netconnection->message, (int)prog->globals.server->total_secrets);
+ MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(total_secrets));
MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
MSG_WriteByte (&host_client->netconnection->message, STAT_TOTALMONSTERS);
- MSG_WriteLong (&host_client->netconnection->message, (int)prog->globals.server->total_monsters);
+ MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(total_monsters));
MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
MSG_WriteByte (&host_client->netconnection->message, STAT_SECRETS);
- MSG_WriteLong (&host_client->netconnection->message, (int)prog->globals.server->found_secrets);
+ MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(found_secrets));
MSG_WriteByte (&host_client->netconnection->message, svc_updatestat);
MSG_WriteByte (&host_client->netconnection->message, STAT_MONSTERS);
- MSG_WriteLong (&host_client->netconnection->message, (int)prog->globals.server->killed_monsters);
+ MSG_WriteLong (&host_client->netconnection->message, (int)PRVM_serverglobalfloat(killed_monsters));
// send a fixangle
// Never send a roll angle, because savegames can catch the server
if (sv.loadgame)
{
MSG_WriteByte (&host_client->netconnection->message, svc_setangle);
- MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->v_angle[0], sv.protocol);
- MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->v_angle[1], sv.protocol);
+ MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[0], sv.protocol);
+ MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, v_angle)[1], sv.protocol);
MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol);
}
else
{
MSG_WriteByte (&host_client->netconnection->message, svc_setangle);
- MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->angles[0], sv.protocol);
- MSG_WriteAngle (&host_client->netconnection->message, host_client->edict->fields.server->angles[1], sv.protocol);
+ MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[0], sv.protocol);
+ MSG_WriteAngle (&host_client->netconnection->message, PRVM_serveredictvector(host_client->edict, angles)[1], sv.protocol);
MSG_WriteAngle (&host_client->netconnection->message, 0, sv.protocol);
}
Host_Begin_f
==================
*/
-void Host_Begin_f (void)
+static void Host_Begin_f (void)
{
- host_client->spawned = true;
+ if (!host_client->spawned)
+ {
+ Con_Print("Begin not valid -- not yet spawned\n");
+ return;
+ }
+ if (host_client->begun)
+ {
+ Con_Print("Begin not valid -- already begun\n");
+ return;
+ }
+ host_client->begun = true;
// LordHavoc: note: this code also exists in SV_DropClient
if (sv.loadgame)
Kicks a user off of the server
==================
*/
-void Host_Kick_f (void)
+static void Host_Kick_f (void)
{
- char *who;
+ const char *who;
const char *message = NULL;
client_t *save;
int i;
if (!sv.active)
return;
- SV_VM_Begin();
save = host_client;
if (Cmd_Argc() > 2 && strcmp(Cmd_Argv(1), "#") == 0)
if (Cmd_Argc() > 2)
{
message = Cmd_Args();
- COM_ParseToken_Simple(&message, false, false);
+ COM_ParseToken_Simple(&message, false, false, true);
if (byNumber)
{
message++; // skip the #
}
host_client = save;
- SV_VM_End();
}
/*
Host_Give_f
==================
*/
-void Host_Give_f (void)
+static void Host_Give_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
const char *t;
int v;
- prvm_eval_t *val;
if (!allowcheats)
{
case '8':
case '9':
// MED 01/04/97 added hipnotic give stuff
- if (gamemode == GAME_HIPNOTIC)
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
{
if (t[0] == '6')
{
if (t[1] == 'a')
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | HIT_PROXIMITY_GUN;
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | HIT_PROXIMITY_GUN;
else
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | IT_GRENADE_LAUNCHER;
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | IT_GRENADE_LAUNCHER;
}
else if (t[0] == '9')
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | HIT_LASER_CANNON;
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | HIT_LASER_CANNON;
else if (t[0] == '0')
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | HIT_MJOLNIR;
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | HIT_MJOLNIR;
else if (t[0] >= '2')
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | (IT_SHOTGUN << (t[0] - '2'));
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | (IT_SHOTGUN << (t[0] - '2'));
}
else
{
if (t[0] >= '2')
- host_client->edict->fields.server->items = (int)host_client->edict->fields.server->items | (IT_SHOTGUN << (t[0] - '2'));
+ PRVM_serveredictfloat(host_client->edict, items) = (int)PRVM_serveredictfloat(host_client->edict, items) | (IT_SHOTGUN << (t[0] - '2'));
}
break;
case 's':
- if (gamemode == GAME_ROGUE && (val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_shells1)))
- val->_float = v;
+ if (gamemode == GAME_ROGUE)
+ PRVM_serveredictfloat(host_client->edict, ammo_shells1) = v;
- host_client->edict->fields.server->ammo_shells = v;
+ PRVM_serveredictfloat(host_client->edict, ammo_shells) = v;
break;
case 'n':
if (gamemode == GAME_ROGUE)
{
- if ((val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_nails1)))
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon <= IT_LIGHTNING)
- host_client->edict->fields.server->ammo_nails = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_nails1) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) <= IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_nails) = v;
}
else
{
- host_client->edict->fields.server->ammo_nails = v;
+ PRVM_serveredictfloat(host_client->edict, ammo_nails) = v;
}
break;
case 'l':
if (gamemode == GAME_ROGUE)
{
- val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_lava_nails);
- if (val)
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon > IT_LIGHTNING)
- host_client->edict->fields.server->ammo_nails = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_lava_nails) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) > IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_nails) = v;
}
break;
case 'r':
if (gamemode == GAME_ROGUE)
{
- val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_rockets1);
- if (val)
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon <= IT_LIGHTNING)
- host_client->edict->fields.server->ammo_rockets = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_rockets1) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) <= IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_rockets) = v;
}
else
{
- host_client->edict->fields.server->ammo_rockets = v;
+ PRVM_serveredictfloat(host_client->edict, ammo_rockets) = v;
}
break;
case 'm':
if (gamemode == GAME_ROGUE)
{
- val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_multi_rockets);
- if (val)
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon > IT_LIGHTNING)
- host_client->edict->fields.server->ammo_rockets = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_multi_rockets) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) > IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_rockets) = v;
}
break;
case 'h':
- host_client->edict->fields.server->health = v;
+ PRVM_serveredictfloat(host_client->edict, health) = v;
break;
case 'c':
if (gamemode == GAME_ROGUE)
{
- val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_cells1);
- if (val)
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon <= IT_LIGHTNING)
- host_client->edict->fields.server->ammo_cells = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_cells1) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) <= IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_cells) = v;
}
else
{
- host_client->edict->fields.server->ammo_cells = v;
+ PRVM_serveredictfloat(host_client->edict, ammo_cells) = v;
}
break;
case 'p':
if (gamemode == GAME_ROGUE)
{
- val = PRVM_EDICTFIELDVALUE(host_client->edict, prog->fieldoffsets.ammo_plasma);
- if (val)
- {
- val->_float = v;
- if (host_client->edict->fields.server->weapon > IT_LIGHTNING)
- host_client->edict->fields.server->ammo_cells = v;
- }
+ PRVM_serveredictfloat(host_client->edict, ammo_plasma) = v;
+ if (PRVM_serveredictfloat(host_client->edict, weapon) > IT_LIGHTNING)
+ PRVM_serveredictfloat(host_client->edict, ammo_cells) = v;
}
break;
}
}
-prvm_edict_t *FindViewthing (void)
+static prvm_edict_t *FindViewthing(prvm_prog_t *prog)
{
int i;
prvm_edict_t *e;
for (i=0 ; i<prog->num_edicts ; i++)
{
e = PRVM_EDICT_NUM(i);
- if (!strcmp (PRVM_GetString(e->fields.server->classname), "viewthing"))
+ if (!strcmp (PRVM_GetString(prog, PRVM_serveredictstring(e, classname)), "viewthing"))
return e;
}
Con_Print("No viewthing on map\n");
Host_Viewmodel_f
==================
*/
-void Host_Viewmodel_f (void)
+static void Host_Viewmodel_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
-
- m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
- if (!m || !m->loaded || !m->Draw)
+ e = FindViewthing(prog);
+ if (e)
{
- Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
- return;
+ m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
+ if (m && m->loaded && m->Draw)
+ {
+ PRVM_serveredictfloat(e, frame) = 0;
+ cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)] = m;
+ }
+ else
+ Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
}
-
- e->fields.server->frame = 0;
- cl.model_precache[(int)e->fields.server->modelindex] = m;
}
/*
Host_Viewframe_f
==================
*/
-void Host_Viewframe_f (void)
+static void Host_Viewframe_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
int f;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
- m = cl.model_precache[(int)e->fields.server->modelindex];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- f = atoi(Cmd_Argv(1));
- if (f >= m->numframes)
- f = m->numframes-1;
+ f = atoi(Cmd_Argv(1));
+ if (f >= m->numframes)
+ f = m->numframes-1;
- e->fields.server->frame = f;
+ PRVM_serveredictfloat(e, frame) = f;
+ }
}
-void PrintFrameName (dp_model_t *m, int frame)
+static void PrintFrameName (dp_model_t *m, int frame)
{
if (m->animscenes)
Con_Printf("frame %i: %s\n", frame, m->animscenes[frame].name);
Host_Viewnext_f
==================
*/
-void Host_Viewnext_f (void)
+static void Host_Viewnext_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
- m = cl.model_precache[(int)e->fields.server->modelindex];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- e->fields.server->frame = e->fields.server->frame + 1;
- if (e->fields.server->frame >= m->numframes)
- e->fields.server->frame = m->numframes - 1;
+ PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) + 1;
+ if (PRVM_serveredictfloat(e, frame) >= m->numframes)
+ PRVM_serveredictfloat(e, frame) = m->numframes - 1;
- PrintFrameName (m, (int)e->fields.server->frame);
+ PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ }
}
/*
Host_Viewprev_f
==================
*/
-void Host_Viewprev_f (void)
+static void Host_Viewprev_f (void)
{
+ prvm_prog_t *prog = SVVM_prog;
prvm_edict_t *e;
dp_model_t *m;
if (!sv.active)
return;
- SV_VM_Begin();
- e = FindViewthing ();
- SV_VM_End();
- if (!e)
- return;
-
- m = cl.model_precache[(int)e->fields.server->modelindex];
+ e = FindViewthing(prog);
+ if (e)
+ {
+ m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
- e->fields.server->frame = e->fields.server->frame - 1;
- if (e->fields.server->frame < 0)
- e->fields.server->frame = 0;
+ PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) - 1;
+ if (PRVM_serveredictfloat(e, frame) < 0)
+ PRVM_serveredictfloat(e, frame) = 0;
- PrintFrameName (m, (int)e->fields.server->frame);
+ PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+ }
}
/*
Host_Startdemos_f
==================
*/
-void Host_Startdemos_f (void)
+static void Host_Startdemos_f (void)
{
int i, c;
Return to looping demos
==================
*/
-void Host_Demos_f (void)
+static void Host_Demos_f (void)
{
if (cls.state == ca_dedicated)
return;
Return to looping demos
==================
*/
-void Host_Stopdemo_f (void)
+static void Host_Stopdemo_f (void)
{
if (!cls.demoplayback)
return;
Host_ShutdownServer ();
}
-void Host_SendCvar_f (void)
+static void Host_SendCvar_f (void)
{
int i;
cvar_t *c;
const char *cvarname;
client_t *old;
+ char vabuf[1024];
if(Cmd_Argc() != 2)
return;
// LordHavoc: if there is no such cvar or if it is private, send a
// reply indicating that it has no value
if(!c || (c->flags & CVAR_PRIVATE))
- Cmd_ForwardStringToServer(va("sentcvar %s", cvarname));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s", cvarname));
else
- Cmd_ForwardStringToServer(va("sentcvar %s \"%s\"", c->name, c->string));
+ Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s \"%s\"", c->name, c->string));
return;
}
- if(!sv.active)// || !prog->funcoffsets.SV_ParseClientCommand)
+ if(!sv.active)// || !PRVM_serverfunction(SV_ParseClientCommand))
return;
old = host_client;
ProQuake rcon support
=====================
*/
-void Host_PQRcon_f (void)
+static void Host_PQRcon_f (void)
{
- int i;
+ int n;
+ const char *e;
lhnetaddress_t to;
lhnetsocket_t *mysocket;
char peer_address[64];
- if (!rcon_password.string || !rcon_password.string[0] || rcon_secure.integer)
+ if (Cmd_Argc() == 1)
{
- Con_Printf ("You must set rcon_password before issuing an pqrcon command, and rcon_secure must be 0.\n");
+ Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
return;
}
- for (i = 0;rcon_password.string[i];i++)
+ if (!rcon_password.string || !rcon_password.string[0] || rcon_secure.integer > 0)
{
- if (ISWHITESPACE(rcon_password.string[i]))
- {
- Con_Printf("rcon_password is not allowed to have any whitespace.\n");
- return;
- }
+ Con_Printf ("You must set rcon_password before issuing an pqrcon command, and rcon_secure must be 0.\n");
+ return;
}
+ e = strchr(rcon_password.string, ' ');
+ n = e ? e-rcon_password.string : (int)strlen(rcon_password.string);
+
if (cls.netcon)
{
InfoString_GetValue(cls.userinfo, "*ip", peer_address, sizeof(peer_address));
mysocket = NetConn_ChooseClientSocketForAddress(&to);
if (mysocket)
{
- SZ_Clear(&net_message);
- MSG_WriteLong (&net_message, 0);
- MSG_WriteByte (&net_message, CCREQ_RCON);
- MSG_WriteString (&net_message, rcon_password.string);
- MSG_WriteString (&net_message, Cmd_Args());
- *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
- NetConn_Write(mysocket, net_message.data, net_message.cursize, &to);
- SZ_Clear (&net_message);
+ sizebuf_t buf;
+ unsigned char bufdata[64];
+ buf.data = bufdata;
+ SZ_Clear(&buf);
+ MSG_WriteLong(&buf, 0);
+ MSG_WriteByte(&buf, CCREQ_RCON);
+ SZ_Write(&buf, (const unsigned char*)rcon_password.string, n);
+ MSG_WriteByte(&buf, 0); // terminate the (possibly partial) string
+ MSG_WriteString(&buf, Cmd_Args());
+ StoreBigLong(buf.data, NETFLAG_CTL | (buf.cursize & NETFLAG_LENGTH_MASK));
+ NetConn_Write(mysocket, buf.data, buf.cursize, &to);
+ SZ_Clear(&buf);
}
}
an unconnected command.
=====================
*/
-void Host_Rcon_f (void) // credit: taken from QuakeWorld
+static void Host_Rcon_f (void) // credit: taken from QuakeWorld
{
- int i;
+ int i, n;
+ const char *e;
lhnetaddress_t to;
lhnetsocket_t *mysocket;
+ char vabuf[1024];
- if (!rcon_password.string || !rcon_password.string[0])
+ if (Cmd_Argc() == 1)
{
- Con_Printf ("You must set rcon_password before issuing an rcon command.\n");
+ Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
return;
}
- for (i = 0;rcon_password.string[i];i++)
+ if (!rcon_password.string || !rcon_password.string[0])
{
- if (ISWHITESPACE(rcon_password.string[i]))
- {
- Con_Printf("rcon_password is not allowed to have any whitespace.\n");
- return;
- }
+ Con_Printf ("You must set rcon_password before issuing an rcon command.\n");
+ return;
}
+ e = strchr(rcon_password.string, ' ');
+ n = e ? e-rcon_password.string : (int)strlen(rcon_password.string);
+
if (cls.netcon)
to = cls.netcon->peeraddress;
else
LHNETADDRESS_FromString(&to, rcon_address.string, sv_netport.integer);
}
mysocket = NetConn_ChooseClientSocketForAddress(&to);
- if (mysocket)
+ if (mysocket && Cmd_Args()[0])
{
// simply put together the rcon packet and send it
- if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer)
+ if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer > 1)
+ {
+ if(cls.rcon_commands[cls.rcon_ringpos][0])
+ {
+ char s[128];
+ LHNETADDRESS_ToString(&cls.rcon_addresses[cls.rcon_ringpos], s, sizeof(s), true);
+ Con_Printf("rcon to %s (for command %s) failed: too many buffered commands (possibly increase MAX_RCONS)\n", s, cls.rcon_commands[cls.rcon_ringpos]);
+ cls.rcon_commands[cls.rcon_ringpos][0] = 0;
+ --cls.rcon_trying;
+ }
+ for (i = 0;i < MAX_RCONS;i++)
+ if(cls.rcon_commands[i][0])
+ if (!LHNETADDRESS_Compare(&to, &cls.rcon_addresses[i]))
+ break;
+ ++cls.rcon_trying;
+ if(i >= MAX_RCONS)
+ NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", &to); // otherwise we'll request the challenge later
+ strlcpy(cls.rcon_commands[cls.rcon_ringpos], Cmd_Args(), sizeof(cls.rcon_commands[cls.rcon_ringpos]));
+ cls.rcon_addresses[cls.rcon_ringpos] = to;
+ cls.rcon_timeout[cls.rcon_ringpos] = realtime + rcon_secure_challengetimeout.value;
+ cls.rcon_ringpos = (cls.rcon_ringpos + 1) % MAX_RCONS;
+ }
+ else if(rcon_secure.integer > 0)
{
char buf[1500];
char argbuf[1500];
dpsnprintf(argbuf, sizeof(argbuf), "%ld.%06d %s", (long) time(NULL), (int) (rand() % 1000000), Cmd_Args());
memcpy(buf, "\377\377\377\377srcon HMAC-MD4 TIME ", 24);
- if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 24), (unsigned char *) argbuf, strlen(argbuf), (unsigned char *) rcon_password.string, strlen(rcon_password.string)))
+ if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 24), (unsigned char *) argbuf, strlen(argbuf), (unsigned char *) rcon_password.string, n))
{
buf[40] = ' ';
strlcpy(buf + 41, argbuf, sizeof(buf) - 41);
}
else
{
- NetConn_WriteString(mysocket, va("\377\377\377\377rcon %s %s", rcon_password.string, Cmd_Args()), &to);
+ NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377rcon %.*s %s", n, rcon_password.string, Cmd_Args()), &to);
}
}
}
Dump userdata / masterdata for a user
====================
*/
-void Host_User_f (void) // credit: taken from QuakeWorld
+static void Host_User_f (void) // credit: taken from QuakeWorld
{
int uid;
int i;
Dump userids for all current players
====================
*/
-void Host_Users_f (void) // credit: taken from QuakeWorld
+static void Host_Users_f (void) // credit: taken from QuakeWorld
{
int i;
int c;
==================
*/
// TODO: shouldn't this be a cvar instead?
-void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
{
char temp[512];
if (Cmd_Argc() != 2)
==================
Casey was here :)
*/
-void Host_FullInfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullInfo_f (void) // credit: taken from QuakeWorld
{
char key[512];
char value[512];
Allow clients to change userinfo
==================
*/
-void Host_SetInfo_f (void) // credit: taken from QuakeWorld
+static void Host_SetInfo_f (void) // credit: taken from QuakeWorld
{
if (Cmd_Argc() == 1)
{
Contents allows \n escape character
====================
*/
-void Host_Packet_f (void) // credit: taken from QuakeWorld
+static void Host_Packet_f (void) // credit: taken from QuakeWorld
{
char send[2048];
int i, l;
*/
void Host_Pings_f (void)
{
- int i, j, ping, packetloss;
+ int i, j, ping, packetloss, movementloss;
char temp[128];
if (!host_client->netconnection)
for (i = 0;i < svs.maxclients;i++)
{
packetloss = 0;
+ movementloss = 0;
if (svs.clients[i].netconnection)
+ {
for (j = 0;j < NETGRAPH_PACKETS;j++)
- if (svs.clients[i].netconnection->incoming_unreliablesize[j] == NETGRAPH_LOSTPACKET)
+ if (svs.clients[i].netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
packetloss++;
- packetloss = packetloss * 100 / NETGRAPH_PACKETS;
+ for (j = 0;j < NETGRAPH_PACKETS;j++)
+ if (svs.clients[i].movement_count[j] < 0)
+ movementloss++;
+ }
+ packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
+ movementloss = (movementloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
ping = (int)floor(svs.clients[i].ping*1000+0.5);
ping = bound(0, ping, 9999);
if (sv.protocol == PROTOCOL_QUAKEWORLD)
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);
+ if(movementloss)
+ dpsnprintf(temp, sizeof(temp), " %d %d,%d", ping, packetloss, movementloss);
+ else
+ dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss);
MSG_WriteUnterminatedString(&host_client->netconnection->message, temp);
}
}
MSG_WriteString(&host_client->netconnection->message, "\n");
}
-void Host_PingPLReport_f(void)
+static void Host_PingPLReport_f(void)
{
+ char *errbyte;
int i;
int l = Cmd_Argc();
if (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));
+ cl.scores[i].qw_packetloss = strtol(Cmd_Argv(1+i*2+1), &errbyte, 0);
+ if(errbyte && *errbyte == ',')
+ cl.scores[i].qw_movementloss = atoi(errbyte + 1);
+ else
+ cl.scores[i].qw_movementloss = 0;
}
}
Cmd_AddCommand_WithClientCommand ("status", Host_Status_f, Host_Status_f, "print server status information");
Cmd_AddCommand ("quit", Host_Quit_f, "quit the game");
- if (gamemode == GAME_NEHAHRA)
- {
- Cmd_AddCommand_WithClientCommand ("max", NULL, Host_God_f, "god mode (invulnerability)");
- Cmd_AddCommand_WithClientCommand ("monster", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)");
- Cmd_AddCommand_WithClientCommand ("scrag", NULL, Host_Fly_f, "fly mode (flight)");
- Cmd_AddCommand_WithClientCommand ("wraith", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)");
- Cmd_AddCommand_WithClientCommand ("gimme", NULL, Host_Give_f, "alter inventory");
- }
- else
- {
- Cmd_AddCommand_WithClientCommand ("god", NULL, Host_God_f, "god mode (invulnerability)");
- Cmd_AddCommand_WithClientCommand ("notarget", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)");
- Cmd_AddCommand_WithClientCommand ("fly", NULL, Host_Fly_f, "fly mode (flight)");
- Cmd_AddCommand_WithClientCommand ("noclip", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)");
- Cmd_AddCommand_WithClientCommand ("give", NULL, Host_Give_f, "alter inventory");
- }
+ Cmd_AddCommand_WithClientCommand ("god", NULL, Host_God_f, "god mode (invulnerability)");
+ Cmd_AddCommand_WithClientCommand ("notarget", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)");
+ Cmd_AddCommand_WithClientCommand ("fly", NULL, Host_Fly_f, "fly mode (flight)");
+ Cmd_AddCommand_WithClientCommand ("noclip", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)");
+ Cmd_AddCommand_WithClientCommand ("give", NULL, Host_Give_f, "alter inventory");
Cmd_AddCommand ("map", Host_Map_f, "kick everyone off the server and start a new level");
Cmd_AddCommand ("restart", Host_Restart_f, "restart current level");
Cmd_AddCommand ("changelevel", Host_Changelevel_f, "change to another level, bringing along all connected clients");
Cmd_AddCommand_WithClientCommand ("say_team", Host_Say_Team_f, Host_Say_Team_f, "send a chat message to your team on the server");
Cmd_AddCommand_WithClientCommand ("tell", Host_Tell_f, Host_Tell_f, "send a chat message to only one person on the server");
Cmd_AddCommand_WithClientCommand ("kill", NULL, Host_Kill_f, "die instantly");
- Cmd_AddCommand_WithClientCommand ("pause", NULL, Host_Pause_f, "pause the game (if the server allows pausing)");
+ Cmd_AddCommand_WithClientCommand ("pause", Host_Pause_f, Host_Pause_f, "pause the game (if the server allows pausing)");
Cmd_AddCommand ("kick", Host_Kick_f, "kick a player off the server by number or name");
Cmd_AddCommand_WithClientCommand ("ping", Host_Ping_f, Host_Ping_f, "print ping times of all players on the server");
Cmd_AddCommand ("load", Host_Loadgame_f, "load a saved game file");
Cmd_AddCommand_WithClientCommand ("color", Host_Color_f, Host_Color_f, "change your player shirt and pants colors");
Cvar_RegisterVariable (&cl_rate);
Cmd_AddCommand_WithClientCommand ("rate", Host_Rate_f, Host_Rate_f, "change your network connection speed");
- if (gamemode == GAME_NEHAHRA)
- {
- Cvar_RegisterVariable (&cl_pmodel);
- Cmd_AddCommand_WithClientCommand ("pmodel", Host_PModel_f, Host_PModel_f, "change your player model choice (Nehahra specific)");
- }
+ Cvar_RegisterVariable (&cl_pmodel);
+ Cmd_AddCommand_WithClientCommand ("pmodel", Host_PModel_f, Host_PModel_f, "(Nehahra-only) change your player model choice");
// BLACK: This isnt game specific anymore (it was GAME_NEXUIZ at first)
Cvar_RegisterVariable (&cl_playermodel);
Cvar_RegisterVariable (&rcon_password);
Cvar_RegisterVariable (&rcon_address);
Cvar_RegisterVariable (&rcon_secure);
+ Cvar_RegisterVariable (&rcon_secure_challengetimeout);
Cmd_AddCommand ("rcon", Host_Rcon_f, "sends a command to the server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's); note: if rcon_secure is set, client and server clocks must be synced e.g. via NTP");
Cmd_AddCommand ("srcon", Host_Rcon_f, "sends a command to the server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's); this always works as if rcon_secure is set; note: client and server clocks must be synced e.g. via NTP");
Cmd_AddCommand ("pqrcon", Host_PQRcon_f, "sends a command to a proquake server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's)");
Cvar_RegisterVariable(&sv_adminnick);
Cvar_RegisterVariable(&sv_status_privacy);
Cvar_RegisterVariable(&sv_status_show_qcstatus);
+ Cvar_RegisterVariable(&sv_namechangetimer);
}
void Host_NoOperation_f(void)