- Con_Print("changelevel <levelname> : continue game on a new level\n");
- return;
- }
- // HACKHACKHACK
- if (!sv.active) {
- Host_Map_f(cmd);
- return;
- }
-
-#ifdef CONFIG_MENU
- // remove menu
- if (key_dest == key_menu || key_dest == key_menu_grabbed)
- MR_ToggleMenu(0);
-#endif
- key_dest = key_game;
-
- SV_SaveSpawnparms ();
- strlcpy(level, Cmd_Argv(cmd, 1), sizeof(level));
- SV_SpawnServer(level);
- if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1", -2);
-}
-
-/*
-==================
-Host_Restart_f
-
-Restarts the current server for a dead player
-==================
-*/
-static void Host_Restart_f(cmd_state_t *cmd)
-{
- char mapname[MAX_QPATH];
-
- if (Cmd_Argc(cmd) != 1)
- {
- Con_Print("restart : restart current level\n");
- return;
- }
- if (!sv.active)
- {
- Con_Print("Only the server may restart\n");
- return;
- }
-
-#ifdef CONFIG_MENU
- // remove menu
- if (key_dest == key_menu || key_dest == key_menu_grabbed)
- MR_ToggleMenu(0);
-#endif
- key_dest = key_game;
-
- strlcpy(mapname, sv.name, sizeof(mapname));
- SV_SpawnServer(mapname);
- if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1", -2);
-}
-
-/*
-==================
-Host_Reconnect_f
-
-This command causes the client to wait for the signon messages again.
-This is sent just before a server changes levels
-==================
-*/
-void Host_Reconnect_f(cmd_state_t *cmd)
-{
- char temp[128];
- // if not connected, reconnect to the most recent server
- if (!cls.netcon)
- {
- // if we have connected to a server recently, the userinfo
- // will still contain its IP address, so get the address...
- InfoString_GetValue(cls.userinfo, "*ip", temp, sizeof(temp));
- if (temp[0])
- CL_EstablishConnection(temp, -1);
- else
- Con_Printf("Reconnect to what server? (you have not connected to a server yet)\n");
- return;
- }
- // if connected, do something based on protocol
- if (cls.protocol == PROTOCOL_QUAKEWORLD)
- {
- // quakeworld can just re-login
- if (cls.qw_downloadmemory) // don't change when downloading
- return;
-
- S_StopAllSounds();
-
- if (cls.state == ca_connected)
- {
- Con_Printf("Server is changing level...\n");
- MSG_WriteChar(&cls.netcon->message, qw_clc_stringcmd);
- MSG_WriteString(&cls.netcon->message, "new");
- }
- }
- else
- {
- // netquake uses reconnect on level changes (silly)
- if (Cmd_Argc(cmd) != 1)
- {
- Con_Print("reconnect : wait for signon messages again\n");
- return;
- }
- if (!cls.signon)
- {
- Con_Print("reconnect: no signon, ignoring reconnect\n");
- return;
- }
- cls.signon = 0; // need new connection messages
- }
-}
-
-/*
-=====================
-Host_Connect_f
-
-User command to connect to server
-=====================
-*/
-static void Host_Connect_f(cmd_state_t *cmd)
-{
- if (Cmd_Argc(cmd) < 2)
- {
- 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 <= 0)
- Cvar_SetQuick(&rcon_password, "");
- CL_EstablishConnection(Cmd_Argv(cmd, 1), 2);
-}
-
-
-/*
-===============================================================================
-
-LOAD / SAVE GAME
-
-===============================================================================
-*/
-
-#define SAVEGAME_VERSION 5
-
-void Host_Savegame_to(prvm_prog_t *prog, const char *name)
-{
- qfile_t *f;
- 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)
- for (i=64 ; i<MAX_LIGHTSTYLES ; i++)
- if (sv.lightstyles[i][0])
- lightstyles = i+1;
-
- isserver = prog == SVVM_prog;
-
- Con_Printf("Saving game to %s...\n", name);
- f = FS_OpenRealFile(name, "wb", false);
- if (!f)
- {
- Con_Print("ERROR: couldn't open.\n");
- return;
- }
-
- FS_Printf(f, "%i\n", SAVEGAME_VERSION);
-
- memset(comment, 0, sizeof(comment));
- if(isserver)
- 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)", prog->name);
- // convert space to _ to make stdio happy
- // LadyHavoc: convert control characters to _ as well
- for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
- if (ISWHITESPACEORCONTROL(comment[i]))
- comment[i] = '_';
- comment[SAVEGAME_COMMENT_LENGTH] = '\0';
-
- FS_Printf(f, "%s\n", comment);
- if(isserver)
- {
- for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
- FS_Printf(f, "%f\n", svs.clients[0].spawn_parms[i]);
- FS_Printf(f, "%d\n", current_skill);
- FS_Printf(f, "%s\n", sv.name);
- FS_Printf(f, "%f\n",sv.time);
- }
- else
- {
- for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
- FS_Printf(f, "(dummy)\n");
- FS_Printf(f, "%d\n", 0);
- FS_Printf(f, "%s\n", "(dummy)");
- FS_Printf(f, "%f\n", realtime);
- }
-
- // write the light styles
- for (i=0 ; i<lightstyles ; i++)
- {
- if (isserver && sv.lightstyles[i][0])
- FS_Printf(f, "%s\n", sv.lightstyles[i]);
- else
- FS_Print(f,"m\n");
- }
-
- 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 (prog, f, PRVM_EDICT_NUM(i));
- }
-
-#if 1
- FS_Printf(f,"/*\n");
- FS_Printf(f,"// DarkPlaces extended savegame\n");
- // darkplaces extension - extra lightstyles, support for color lightstyles
- for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
- if (isserver && sv.lightstyles[i][0])
- FS_Printf(f, "sv.lightstyles %i %s\n", i, sv.lightstyles[i]);
-
- // darkplaces extension - model precaches
- for (i=1 ; i<MAX_MODELS ; i++)
- if (sv.model_precache[i][0])
- FS_Printf(f,"sv.model_precache %i %s\n", i, sv.model_precache[i]);
-
- // darkplaces extension - sound precaches
- 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 = (int)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
-
- FS_Close (f);
- Con_Print("done.\n");
-}
-
-/*
-===============
-Host_Savegame_f
-===============
-*/
-static void Host_Savegame_f(cmd_state_t *cmd)
-{
- prvm_prog_t *prog = SVVM_prog;
- char name[MAX_QPATH];
- qboolean deadflag = false;
-
- if (!sv.active)
- {
- Con_Print("Can't save - no server running.\n");
- return;
- }
-
- deadflag = cl.islocalgame && svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag);
-
- if (cl.islocalgame)
- {
- // singleplayer checks
- if (cl.intermission)
- {
- Con_Print("Can't save in intermission.\n");
- return;
- }
-
- if (deadflag)
- {
- Con_Print("Can't savegame with a dead player\n");
- return;
- }
- }
- else
- Con_Warn("Warning: saving a multiplayer game may have strange results when restored (to properly resume, all players must join in the same player slots and then the game can be reloaded).\n");
-
- if (Cmd_Argc(cmd) != 2)
- {
- Con_Print("save <savename> : save a game\n");
- return;
- }
-
- if (strstr(Cmd_Argv(cmd, 1), ".."))
- {
- Con_Print("Relative pathnames are not allowed.\n");
- return;
- }
-
- strlcpy (name, Cmd_Argv(cmd, 1), sizeof (name));
- FS_DefaultExtension (name, ".sav", sizeof (name));
-
- Host_Savegame_to(prog, name);
-}
-
-
-/*
-===============
-Host_Loadgame_f
-===============
-*/
-
-static void Host_Loadgame_f(cmd_state_t *cmd)
-{
- prvm_prog_t *prog = SVVM_prog;
- char filename[MAX_QPATH];
- char mapname[MAX_QPATH];
- float time;
- const char *start;
- const char *end;
- const char *t;
- char *text;
- prvm_edict_t *ent;
- int i, k, numbuffers;
- int entnum;
- int version;
- float spawn_parms[NUM_SPAWN_PARMS];
- prvm_stringbuffer_t *stringbuffer;
-
- if (Cmd_Argc(cmd) != 2)
- {
- Con_Print("load <savename> : load a game\n");
- return;
- }
-
- strlcpy (filename, Cmd_Argv(cmd, 1), sizeof(filename));
- FS_DefaultExtension (filename, ".sav", sizeof (filename));
-
- Con_Printf("Loading game from %s...\n", filename);
-
- // stop playing demos
- if (cls.demoplayback)
- CL_Disconnect ();
-
-#ifdef CONFIG_MENU
- // remove menu
- if (key_dest == key_menu || key_dest == key_menu_grabbed)
- MR_ToggleMenu(0);
-#endif
- key_dest = key_game;
-
- cls.demonum = -1; // stop demo loop in case this fails
-
- t = text = (char *)FS_LoadFile (filename, tempmempool, false, NULL);
- if (!text)
- {
- Con_Print("ERROR: couldn't open.\n");
- return;
- }
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading version\n");
-
- // version
- COM_ParseToken_Simple(&t, false, false, true);
- version = atoi(com_token);
- if (version != SAVEGAME_VERSION)
- {
- Mem_Free(text);
- Con_Printf("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
- return;
- }
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading description\n");
-
- // description
- COM_ParseToken_Simple(&t, false, false, true);
-
- for (i = 0;i < NUM_SPAWN_PARMS;i++)
- {
- COM_ParseToken_Simple(&t, false, false, true);
- spawn_parms[i] = atof(com_token);
- }
- // skill
- 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 (&cvars_all, "skill", (float)current_skill);
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading mapname\n");
-
- // mapname
- 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, true);
- time = atof(com_token);
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: spawning server\n");
-
- SV_SpawnServer (mapname);
- if (!sv.active)
- {
- Mem_Free(text);
- Con_Print("Couldn't load map\n");
- return;
- }
- sv.paused = true; // pause until all clients connect
- sv.loadgame = true;
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading light styles\n");
-
-// load the light styles
-
- // -1 is the globals
- entnum = -1;
-
- for (i = 0;i < MAX_LIGHTSTYLES;i++)
- {
- // light style
- start = t;
- 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] == '{')
- {
- t = start;
- break;
- }
- strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
- }
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: skipping until globals\n");
-
- // now skip everything before the first opening brace
- // (this is for forward compatibility, so that older versions (at
- // least ones with this fix) can load savegames with extra data before the
- // first brace, as might be produced by a later engine version)
- for (;;)
- {
- start = t;
- if (!COM_ParseToken_Simple(&t, false, false, true))
- break;
- if (com_token[0] == '{')
- {
- t = start;
- break;
- }
- }
-
- // 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, true))
- if (!strcmp(com_token, "}"))
- break;
- if (!COM_ParseToken_Simple(&start, false, false, true))
- {
- // end of file
- break;
- }
- if (strcmp(com_token,"{"))
- {
- Mem_Free(text);
- Host_Error ("First token isn't a brace");
- }
-
- if (entnum == -1)
- {
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading globals\n");
-
- // parse the global vars
- PRVM_ED_ParseGlobals (prog, start);
-
- // restore the autocvar globals
- Cvar_UpdateAllAutoCvars(prog->console_cmd->cvars);
- }
- else
- {
- // parse an edict
- if (entnum >= MAX_EDICTS)
- {
- Mem_Free(text);
- Host_Error("Host_PerformLoadGame: too many edicts in save file (reached MAX_EDICTS %i)", MAX_EDICTS);
- }
- while (entnum >= prog->max_edicts)
- PRVM_MEM_IncreaseEdicts(prog);
- ent = PRVM_EDICT_NUM(entnum);
- 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 (prog, start, ent);
-
- // link it into the bsp tree
- if (!ent->priv.server->free && !VectorCompare(PRVM_serveredictvector(ent, absmin), PRVM_serveredictvector(ent, absmax)))
- SV_LinkEdict(ent);
- }
-
- end = t;
- entnum++;
- }
-
- prog->num_edicts = entnum;
- sv.time = time;
-
- for (i = 0;i < NUM_SPAWN_PARMS;i++)
- svs.clients[0].spawn_parms[i] = spawn_parms[i];
-
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: skipping until extended data\n");
-
- // read extended data if present
- // the extended data is stored inside a /* */ comment block, which the
- // parser intentionally skips, so we have to check for it manually here
- if(end)
- {
- while (*end == '\r' || *end == '\n')
- end++;
- if (end[0] == '/' && end[1] == '*' && (end[2] == '\r' || end[2] == '\n'))
- {
- if(developer_entityparsing.integer)
- Con_Printf("Host_Loadgame_f: loading extended data\n");
-
- Con_Printf("Loading extended DarkPlaces savegame\n");
- t = end + 2;
- 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));
- BufStr_Flush(prog);
-
- while (COM_ParseToken_Simple(&t, false, false, true))
- {
- if (!strcmp(com_token, "sv.lightstyles"))
- {
- COM_ParseToken_Simple(&t, false, false, true);
- i = atoi(com_token);
- COM_ParseToken_Simple(&t, false, false, true);
- if (i >= 0 && i < MAX_LIGHTSTYLES)
- strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
- else
- Con_Printf("unsupported lightstyle %i \"%s\"\n", i, com_token);
- }
- else if (!strcmp(com_token, "sv.model_precache"))
- {
- COM_ParseToken_Simple(&t, false, false, true);
- i = atoi(com_token);
- 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.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, true);
- i = atoi(com_token);
- 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_Errorf("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_Errorf("failed to create stringbuffer %i \"%s\"\n", i, com_token);
- }
- }
- // skip any trailing text or unrecognized commands
- 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 = (int)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");
-
- // make sure we're connected to loopback
- if (sv.active && cls.state == ca_disconnected)
- CL_EstablishConnection("local:1", -2);
-}
-
-//============================================================================
-
-/*
-======================
-Host_Name_f
-======================
-*/
-cvar_t cl_name = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_name", "player", "internal storage cvar for current player name (changed by name command)"};
-static void Host_Name_f(cmd_state_t *cmd)
-{
- prvm_prog_t *prog = SVVM_prog;
- int i, j;
- qboolean valid_colors;
- const char *newNameSource;
- char newName[sizeof(host_client->name)];
-
- if (Cmd_Argc (cmd) == 1)
- {
- if (cmd->source == src_command)
- {
- Con_Printf("name: %s\n", cl_name.string);
- }
- return;
- }
-
- if (Cmd_Argc (cmd) == 2)
- newNameSource = Cmd_Argv(cmd, 1);
- else
- newNameSource = Cmd_Args(cmd);
-
- strlcpy(newName, newNameSource, sizeof(newName));
-
- if (cmd->source == src_command)
- {
- Cvar_Set (&cvars_all, "_cl_name", newName);
- if (strlen(newNameSource) >= sizeof(newName)) // overflowed
- {
- Con_Printf("Your name is longer than %i chars! It has been truncated.\n", (int) (sizeof(newName) - 1));
- Con_Printf("name: %s\n", cl_name.string);
- }
- return;
- }
-
- if (realtime < host_client->nametime)
- {
- 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 + 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));
-
- for (i = 0, j = 0;host_client->name[i];i++)
- if (host_client->name[i] != '\r' && host_client->name[i] != '\n')
- host_client->name[j++] = host_client->name[i];
- host_client->name[j] = 0;
-
- if(host_client->name[0] == 1 || host_client->name[0] == 2)
- // may interfere with chat area, and will needlessly beep; so let's add a ^7
- {
- memmove(host_client->name + 2, host_client->name, sizeof(host_client->name) - 2);
- host_client->name[sizeof(host_client->name) - 1] = 0;
- host_client->name[0] = STRING_COLOR_TAG;
- host_client->name[1] = '0' + STRING_COLOR_DEFAULT;
- }
-
- 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;
- l = strlen(host_client->name);
- if(l < sizeof(host_client->name) - 1)
- {
- // duplicate the color tag to escape it
- host_client->name[i] = STRING_COLOR_TAG;
- host_client->name[i+1] = 0;
- //Con_DPrintf("abuse detected, adding another trailing color tag\n");
- }
- else
- {
- // remove the last character to fix the color code
- host_client->name[l-1] = 0;
- //Con_DPrintf("abuse detected, removing a trailing color tag\n");
- }
- }
-
- // find the last color tag offset and decide if we need to add a reset tag
- for (i = 0, j = -1;host_client->name[i];i++)
- {
- if (host_client->name[i] == STRING_COLOR_TAG)
- {
- if (host_client->name[i+1] >= '0' && host_client->name[i+1] <= '9')
- {
- j = i;
- // if this happens to be a reset tag then we don't need one
- if (host_client->name[i+1] == '0' + STRING_COLOR_DEFAULT)
- j = -1;
- i++;
- continue;
- }
- if (host_client->name[i+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(host_client->name[i+2]) && isxdigit(host_client->name[i+3]) && isxdigit(host_client->name[i+4]))
- {
- j = i;
- i += 4;
- continue;
- }
- if (host_client->name[i+1] == STRING_COLOR_TAG)
- {
- i++;
- continue;
- }
- }
- }
- // does not end in the default color string, so add it
- 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);
-
- PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
- if (strcmp(host_client->old_name, host_client->name))
- {
- 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
- MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
- MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
- MSG_WriteString (&sv.reliable_datagram, host_client->name);
- SV_WriteNetnameIntoDemo(host_client);
- }
-}
-
-/*
-======================
-Host_Playermodel_f
-======================
-*/
-cvar_t cl_playermodel = {CVAR_CLIENT | 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
-static void Host_Playermodel_f(cmd_state_t *cmd)
-{
- prvm_prog_t *prog = SVVM_prog;
- int i, j;
- char newPath[sizeof(host_client->playermodel)];
-
- if (Cmd_Argc (cmd) == 1)
- {
- if (cmd->source == src_command)
- {
- Con_Printf("\"playermodel\" is \"%s\"\n", cl_playermodel.string);
- }
- return;
- }
-
- if (Cmd_Argc (cmd) == 2)
- strlcpy (newPath, Cmd_Argv(cmd, 1), sizeof (newPath));
- else
- strlcpy (newPath, Cmd_Args(cmd), sizeof (newPath));
-
- for (i = 0, j = 0;newPath[i];i++)
- if (newPath[i] != '\r' && newPath[i] != '\n')
- newPath[j++] = newPath[i];
- newPath[j] = 0;
-
- if (cmd->source == src_command)
- {
- Cvar_Set (&cvars_all, "_cl_playermodel", newPath);
- return;
- }
-
- /*
- if (realtime < host_client->nametime)
- {
- SV_ClientPrintf("You can't change playermodel more than once every 5 seconds!\n");
- return;
- }
-
- host_client->nametime = realtime + 5;
- */
-
- // point the string back at updateclient->name to keep it safe
- strlcpy (host_client->playermodel, newPath, sizeof (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));
- /*// send notification to all clients
- MSG_WriteByte (&sv.reliable_datagram, svc_updatepmodel);
- MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
- MSG_WriteString (&sv.reliable_datagram, host_client->playermodel);*/
- }
-}
-
-/*
-======================
-Host_Playerskin_f
-======================
-*/
-cvar_t cl_playerskin = {CVAR_CLIENT | 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(cmd_state_t *cmd)
-{
- prvm_prog_t *prog = SVVM_prog;
- int i, j;
- char newPath[sizeof(host_client->playerskin)];
-
- if (Cmd_Argc (cmd) == 1)
- {
- if (cmd->source == src_command)
- {
- Con_Printf("\"playerskin\" is \"%s\"\n", cl_playerskin.string);
- }