This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/server/sv_cmds.c

990 lines
21 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
sv_cmds.c - server console commands
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
2007-06-21 22:00:00 +02:00
2008-06-09 22:00:00 +02:00
#include "common.h"
2007-06-21 22:00:00 +02:00
#include "server.h"
2008-07-16 22:00:00 +02:00
/*
=================
SV_ClientPrintf
Sends text across to be displayed if the level passes
=================
*/
2009-06-24 22:00:00 +02:00
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
2008-07-16 22:00:00 +02:00
{
va_list argptr;
2008-07-23 22:00:00 +02:00
char string[MAX_SYSPATH];
2009-06-24 22:00:00 +02:00
2011-04-05 22:00:00 +02:00
if( level < cl->messagelevel || cl->fakeclient )
2009-06-24 22:00:00 +02:00
return;
2008-07-16 22:00:00 +02:00
va_start( argptr, fmt );
2011-03-09 22:00:00 +01:00
Q_vsprintf( string, fmt, argptr );
2008-07-16 22:00:00 +02:00
va_end( argptr );
2010-08-04 22:00:00 +02:00
BF_WriteByte( &cl->netchan.message, svc_print );
BF_WriteByte( &cl->netchan.message, level );
BF_WriteString( &cl->netchan.message, string );
2008-07-16 22:00:00 +02:00
}
/*
=================
SV_BroadcastPrintf
Sends text to all active clients
=================
*/
2009-06-24 22:00:00 +02:00
void SV_BroadcastPrintf( int level, char *fmt, ... )
2008-07-16 22:00:00 +02:00
{
2008-07-23 22:00:00 +02:00
char string[MAX_SYSPATH];
2008-07-16 22:00:00 +02:00
va_list argptr;
sv_client_t *cl;
int i;
2010-10-15 22:00:00 +02:00
if( !sv.state ) return;
2008-07-16 22:00:00 +02:00
va_start( argptr, fmt );
2011-03-09 22:00:00 +01:00
Q_vsprintf( string, fmt, argptr );
2008-07-16 22:00:00 +02:00
va_end( argptr );
// echo to console
2008-07-31 22:00:00 +02:00
if( host.type == HOST_DEDICATED ) Msg( "%s", string );
2011-04-05 22:00:00 +02:00
2009-09-25 22:00:00 +02:00
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
2008-07-16 22:00:00 +02:00
{
2009-06-24 22:00:00 +02:00
if( level < cl->messagelevel ) continue;
2008-07-16 22:00:00 +02:00
if( cl->state != cs_spawned ) continue;
2010-10-09 22:00:00 +02:00
if( cl->fakeclient ) continue;
2010-08-04 22:00:00 +02:00
BF_WriteByte( &cl->netchan.message, svc_print );
BF_WriteByte( &cl->netchan.message, level );
BF_WriteString( &cl->netchan.message, string );
2008-07-16 22:00:00 +02:00
}
}
/*
=================
SV_BroadcastCommand
Sends text to all active clients
=================
*/
void SV_BroadcastCommand( char *fmt, ... )
{
va_list argptr;
2008-07-23 22:00:00 +02:00
char string[MAX_SYSPATH];
2008-07-16 22:00:00 +02:00
if( !sv.state ) return;
va_start( argptr, fmt );
2011-03-09 22:00:00 +01:00
Q_vsprintf( string, fmt, argptr );
2008-07-16 22:00:00 +02:00
va_end( argptr );
2010-10-09 22:00:00 +02:00
BF_WriteByte( &sv.reliable_datagram, svc_stufftext );
BF_WriteString( &sv.reliable_datagram, string );
2008-07-16 22:00:00 +02:00
}
2007-06-21 22:00:00 +02:00
/*
==================
SV_SetPlayer
Sets sv_client and sv_player to the player with idnum Cmd_Argv(1)
==================
*/
2010-10-26 22:00:00 +02:00
qboolean SV_SetPlayer( void )
2007-06-21 22:00:00 +02:00
{
char *s;
2008-07-09 22:00:00 +02:00
sv_client_t *cl;
2007-11-17 22:00:00 +01:00
int i, idnum;
2007-06-21 22:00:00 +02:00
2012-12-16 21:00:00 +01:00
if( !svs.clients )
{
Msg( "^3no server running.\n" );
return false;
}
2010-12-21 22:00:00 +01:00
if( sv_maxclients->integer == 1 || Cmd_Argc() < 2 )
2009-11-25 22:00:00 +01:00
{
2011-04-05 22:00:00 +02:00
// special case for local client
2011-04-08 22:00:00 +02:00
svs.currentPlayer = svs.clients;
2011-04-21 22:00:00 +02:00
svs.currentPlayerNum = 0;
2009-11-25 22:00:00 +01:00
return true;
}
s = Cmd_Argv( 1 );
2007-06-21 22:00:00 +02:00
// numeric values are just slot numbers
2012-12-16 21:00:00 +01:00
if( Q_isdigit( s ) || (s[0] == '-' && Q_isdigit( s + 1 )))
2007-06-21 22:00:00 +02:00
{
2011-04-08 22:00:00 +02:00
idnum = Q_atoi( s );
2009-09-25 22:00:00 +02:00
if( idnum < 0 || idnum >= sv_maxclients->integer )
2007-06-21 22:00:00 +02:00
{
2009-09-25 22:00:00 +02:00
Msg( "Bad client slot: %i\n", idnum );
2007-06-21 22:00:00 +02:00
return false;
}
2011-04-05 22:00:00 +02:00
2011-04-08 22:00:00 +02:00
svs.currentPlayer = &svs.clients[idnum];
2011-04-21 22:00:00 +02:00
svs.currentPlayerNum = idnum;
2011-04-08 22:00:00 +02:00
if( !svs.currentPlayer->state )
2007-06-21 22:00:00 +02:00
{
2009-09-25 22:00:00 +02:00
Msg( "Client %i is not active\n", idnum );
2007-06-21 22:00:00 +02:00
return false;
}
return true;
}
// check for a name match
2009-09-25 22:00:00 +02:00
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
2007-06-21 22:00:00 +02:00
{
2008-07-31 22:00:00 +02:00
if( !cl->state ) continue;
2011-03-09 22:00:00 +01:00
if( !Q_strcmp( cl->name, s ))
2007-06-21 22:00:00 +02:00
{
2011-04-08 22:00:00 +02:00
svs.currentPlayer = cl;
2011-04-21 22:00:00 +02:00
svs.currentPlayerNum = (cl - svs.clients);
2007-06-21 22:00:00 +02:00
return true;
}
}
2011-04-05 22:00:00 +02:00
2008-07-31 22:00:00 +02:00
Msg( "Userid %s is not on the server\n", s );
2011-04-08 22:00:00 +02:00
svs.currentPlayer = NULL;
2011-04-21 22:00:00 +02:00
svs.currentPlayerNum = 0;
2011-04-08 22:00:00 +02:00
2007-06-21 22:00:00 +02:00
return false;
}
/*
==================
2007-11-17 22:00:00 +01:00
SV_Map_f
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
Goes directly to a given map without any savegame archiving.
For development work
2007-06-21 22:00:00 +02:00
==================
*/
2007-11-17 22:00:00 +01:00
void SV_Map_f( void )
2007-06-21 22:00:00 +02:00
{
2009-09-28 22:00:00 +02:00
char *spawn_entity;
2010-04-02 22:00:00 +02:00
string mapname;
int flags;
2007-11-17 22:00:00 +01:00
2008-07-31 22:00:00 +02:00
if( Cmd_Argc() != 2 )
2007-10-19 22:00:00 +02:00
{
2010-04-02 22:00:00 +02:00
Msg( "Usage: map <mapname>\n" );
2007-10-19 22:00:00 +02:00
return;
}
2010-04-02 22:00:00 +02:00
// hold mapname to other place
2011-03-09 22:00:00 +01:00
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
2010-04-02 22:00:00 +02:00
2009-09-28 22:00:00 +02:00
// determine spawn entity classname
2010-10-21 22:00:00 +02:00
if( sv_maxclients->integer == 1 )
spawn_entity = GI->sp_entity;
else spawn_entity = GI->mp_entity;
2009-09-28 22:00:00 +02:00
2010-04-02 22:00:00 +02:00
flags = SV_MapIsValid( mapname, spawn_entity, NULL );
2011-01-06 22:00:00 +01:00
if( flags & MAP_INVALID_VERSION )
{
Msg( "SV_NewMap: map %s is invalid or not supported\n", mapname );
return;
}
2010-04-02 22:00:00 +02:00
if(!( flags & MAP_IS_EXIST ))
2007-11-17 22:00:00 +01:00
{
2010-04-02 22:00:00 +02:00
Msg( "SV_NewMap: map %s doesn't exist\n", mapname );
2007-11-17 22:00:00 +01:00
return;
}
2007-06-21 22:00:00 +02:00
2010-04-02 22:00:00 +02:00
if(!( flags & MAP_HAS_SPAWNPOINT ))
{
Msg( "SV_NewMap: map %s doesn't have a valid spawnpoint\n", mapname );
return;
}
2007-06-21 22:00:00 +02:00
2014-05-09 22:00:00 +02:00
// init network stuff
NET_Config(( sv_maxclients->integer > 1 ));
2012-12-16 21:00:00 +01:00
// changing singleplayer to multiplayer or back. refresh the player count
if(( sv_maxclients->modified ) || ( deathmatch->modified ) || ( coop->modified ) || ( teamplay->modified ))
Host_ShutdownServer();
2011-04-05 22:00:00 +02:00
SCR_BeginLoadingPlaque( false );
2010-12-09 22:00:00 +01:00
2012-08-29 22:00:00 +02:00
sv.changelevel = false;
2011-02-22 22:00:00 +01:00
sv.background = false;
2010-04-02 22:00:00 +02:00
sv.loadgame = false; // set right state
SV_ClearSaveDir (); // delete all temporary *.hl files
2010-04-09 22:00:00 +02:00
SV_DeactivateServer();
2010-04-02 22:00:00 +02:00
SV_SpawnServer( mapname, NULL );
SV_LevelInit( mapname, NULL, NULL, false );
2009-09-28 22:00:00 +02:00
SV_ActivateServer ();
2007-11-17 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
2011-02-22 22:00:00 +01:00
/*
==================
SV_MapBackground_f
Set background map (enable physics in menu)
==================
*/
void SV_MapBackground_f( void )
{
string mapname;
int flags;
if( Cmd_Argc() != 2 )
{
Msg( "Usage: map_background <mapname>\n" );
return;
}
2011-02-26 22:00:00 +01:00
if( sv.state == ss_active && !sv.background )
{
Msg( "SV_NewMap: can't set background map while game is active\n" );
return;
}
2011-02-22 22:00:00 +01:00
// hold mapname to other place
2011-03-09 22:00:00 +01:00
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
2011-02-22 22:00:00 +01:00
flags = SV_MapIsValid( mapname, GI->sp_entity, NULL );
if(!( flags & MAP_IS_EXIST ))
{
Msg( "SV_NewMap: map %s doesn't exist\n", mapname );
return;
}
// background maps allow without spawnpoints (just throw warning)
if(!( flags & MAP_HAS_SPAWNPOINT ))
MsgDev( D_WARN, "SV_NewMap: map %s doesn't have a valid spawnpoint\n", mapname );
2011-03-09 22:00:00 +01:00
Q_strncpy( host.finalmsg, "", MAX_STRING );
2011-02-22 22:00:00 +01:00
SV_Shutdown( true );
NET_Config ( false ); // close network sockets
2012-08-29 22:00:00 +02:00
sv.changelevel = false;
2011-02-22 22:00:00 +01:00
sv.background = true;
sv.loadgame = false; // set right state
// reset all multiplayer cvars
Cvar_FullSet( "coop", "0", CVAR_LATCH );
Cvar_FullSet( "teamplay", "0", CVAR_LATCH );
Cvar_FullSet( "deathmatch", "0", CVAR_LATCH );
Cvar_FullSet( "maxplayers", "1", CVAR_LATCH );
2011-04-05 22:00:00 +02:00
SCR_BeginLoadingPlaque( true );
2011-02-27 22:00:00 +01:00
2011-02-22 22:00:00 +01:00
SV_SpawnServer( mapname, NULL );
SV_LevelInit( mapname, NULL, NULL, false );
SV_ActivateServer ();
}
2014-05-17 22:00:00 +02:00
/*
==============
SV_NewGame_f
==============
*/
void SV_NewGame_f( void )
2008-01-20 22:00:00 +01:00
{
2010-03-25 22:00:00 +01:00
if( Cmd_Argc() != 1 )
{
Msg( "Usage: newgame\n" );
return;
}
Host_NewGame( GI->startmap, false );
2008-01-20 22:00:00 +01:00
}
2014-05-17 22:00:00 +02:00
/*
==============
SV_HazardCourse_f
==============
*/
2010-07-29 22:00:00 +02:00
void SV_HazardCourse_f( void )
{
if( Cmd_Argc() != 1 )
{
Msg( "Usage: hazardcourse\n" );
return;
}
Host_NewGame( GI->trainmap, false );
}
2014-05-17 22:00:00 +02:00
/*
==============
SV_EndGame_f
==============
*/
void SV_EndGame_f( void )
{
Host_EndGame( Cmd_Argv( 1 ));
}
/*
==============
SV_KillGame_f
==============
*/
void SV_KillGame_f( void )
2009-10-16 22:00:00 +02:00
{
2010-03-25 22:00:00 +01:00
Host_EndGame( "The End" );
2009-10-16 22:00:00 +02:00
}
2007-06-21 22:00:00 +02:00
/*
==============
2007-11-17 22:00:00 +01:00
SV_Load_f
2007-06-21 22:00:00 +02:00
==============
*/
2007-11-17 22:00:00 +01:00
void SV_Load_f( void )
2007-06-21 22:00:00 +02:00
{
2009-09-25 22:00:00 +02:00
if( Cmd_Argc() != 2 )
2007-06-21 22:00:00 +02:00
{
2010-03-25 22:00:00 +01:00
Msg( "Usage: load <savename>\n" );
2007-11-17 22:00:00 +01:00
return;
}
2010-03-25 22:00:00 +01:00
SV_LoadGame( Cmd_Argv( 1 ));
2007-06-21 22:00:00 +02:00
}
2009-10-16 22:00:00 +02:00
/*
==============
SV_QuickLoad_f
==============
*/
void SV_QuickLoad_f( void )
{
2011-04-06 22:00:00 +02:00
Cbuf_AddText( "echo Quick Loading...; wait; load quick" );
2009-10-16 22:00:00 +02:00
}
2007-06-21 22:00:00 +02:00
/*
==============
2007-11-17 22:00:00 +01:00
SV_Save_f
2007-06-21 22:00:00 +02:00
==============
*/
2007-11-17 22:00:00 +01:00
void SV_Save_f( void )
2007-06-21 22:00:00 +02:00
{
2009-12-11 22:00:00 +01:00
const char *name;
2010-03-25 22:00:00 +01:00
switch( Cmd_Argc() )
2010-01-07 22:00:00 +01:00
{
2010-03-25 22:00:00 +01:00
case 1: name = "new"; break;
case 2: name = Cmd_Argv( 1 ); break;
default:
2010-01-07 22:00:00 +01:00
Msg( "Usage: save <savename>\n" );
return;
}
2010-03-25 22:00:00 +01:00
SV_SaveGame( name );
2009-09-10 22:00:00 +02:00
}
2009-10-16 22:00:00 +02:00
/*
==============
SV_QuickSave_f
==============
*/
void SV_QuickSave_f( void )
{
2011-04-06 22:00:00 +02:00
Cbuf_AddText( "echo Quick Saving...; wait; save quick" );
2009-10-16 22:00:00 +02:00
}
2009-09-10 22:00:00 +02:00
/*
==============
2010-01-07 22:00:00 +01:00
SV_DeleteSave_f
2009-09-10 22:00:00 +02:00
==============
*/
2010-01-07 22:00:00 +01:00
void SV_DeleteSave_f( void )
2009-09-10 22:00:00 +02:00
{
if( Cmd_Argc() != 2 )
{
2010-01-07 22:00:00 +01:00
Msg( "Usage: delsave <name>\n" );
2009-09-10 22:00:00 +02:00
return;
}
2007-06-21 22:00:00 +02:00
2009-09-10 22:00:00 +02:00
// delete save and saveshot
2010-03-27 22:00:00 +01:00
FS_Delete( va( "save/%s.sav", Cmd_Argv( 1 )));
2011-02-15 22:00:00 +01:00
FS_Delete( va( "save/%s.bmp", Cmd_Argv( 1 )));
2009-01-09 22:00:00 +01:00
}
/*
==============
SV_AutoSave_f
==============
*/
void SV_AutoSave_f( void )
{
2014-01-01 21:00:00 +01:00
if( Cmd_Argc() != 1 )
{
Msg( "Usage: autosave\n" );
return;
}
2010-03-25 22:00:00 +01:00
SV_SaveGame( "autosave" );
2007-11-17 22:00:00 +01:00
}
/*
==================
SV_ChangeLevel_f
Saves the state of the map just being exited and goes to a new map.
==================
*/
void SV_ChangeLevel_f( void )
{
2010-04-02 22:00:00 +02:00
char *spawn_entity, *mapname;
int flags, c = Cmd_Argc();
2014-05-11 22:00:00 +02:00
if( c < 2 )
{
Msg( "Usage: changelevel <map> [landmark]\n" );
return;
}
2010-04-02 22:00:00 +02:00
mapname = Cmd_Argv( 1 );
2007-11-17 22:00:00 +01:00
2009-09-28 22:00:00 +02:00
// determine spawn entity classname
2010-10-21 22:00:00 +02:00
if( sv_maxclients->integer == 1 )
spawn_entity = GI->sp_entity;
else spawn_entity = GI->mp_entity;
2009-09-28 22:00:00 +02:00
2010-04-02 22:00:00 +02:00
flags = SV_MapIsValid( mapname, spawn_entity, Cmd_Argv( 2 ));
2011-01-06 22:00:00 +01:00
if( flags & MAP_INVALID_VERSION )
{
Msg( "SV_ChangeLevel: map %s is invalid or not supported\n", mapname );
return;
}
2010-04-02 22:00:00 +02:00
if(!( flags & MAP_IS_EXIST ))
2007-06-21 22:00:00 +02:00
{
2010-04-02 22:00:00 +02:00
Msg( "SV_ChangeLevel: map %s doesn't exist\n", mapname );
2007-06-21 22:00:00 +02:00
return;
}
2014-05-11 22:00:00 +02:00
if( c >= 3 && !( flags & MAP_HAS_LANDMARK ))
2010-04-02 22:00:00 +02:00
{
2012-05-23 22:00:00 +02:00
if( sv_validate_changelevel->integer )
{
// NOTE: we find valid map but specified landmark it's doesn't exist
// run simple changelevel like in q1, throw warning
MsgDev( D_INFO, "SV_ChangeLevel: map %s is exist but doesn't contain\n", mapname );
MsgDev( D_INFO, "landmark with name %s. Run classic quake changelevel\n", Cmd_Argv( 2 ));
c = 2; // reduce args
}
2010-04-02 22:00:00 +02:00
}
2014-05-11 22:00:00 +02:00
if( c >= 3 && !Q_stricmp( sv.name, Cmd_Argv( 1 )))
2010-04-02 22:00:00 +02:00
{
MsgDev( D_INFO, "SV_ChangeLevel: can't changelevel with same map. Ignored.\n" );
return;
}
if( c == 2 && !( flags & MAP_HAS_SPAWNPOINT ))
{
2012-05-23 22:00:00 +02:00
if( sv_validate_changelevel->integer )
{
MsgDev( D_INFO, "SV_ChangeLevel: map %s doesn't have a valid spawnpoint. Ignored.\n", mapname );
return;
}
2010-04-02 22:00:00 +02:00
}
2012-06-25 22:00:00 +02:00
// bad changelevel position invoke enables in one-way transtion
if( sv.net_framenum < 15 )
{
if( sv_validate_changelevel->integer )
{
MsgDev( D_INFO, "SV_ChangeLevel: a infinite changelevel detected.\n" );
MsgDev( D_INFO, "Changelevel will be disabled until a next save\\restore.\n" );
return; // lock with svs.spawncount here
}
}
if( sv.state != ss_active )
{
MsgDev( D_INFO, "Only the server may changelevel\n" );
return;
}
2011-04-05 22:00:00 +02:00
SCR_BeginLoadingPlaque( false );
2010-12-09 22:00:00 +01:00
2012-06-25 22:00:00 +02:00
if( sv.background )
2007-06-21 22:00:00 +02:00
{
2009-09-28 22:00:00 +02:00
// just load map
2010-04-02 22:00:00 +02:00
Cbuf_AddText( va( "map %s\n", mapname ));
2007-06-21 22:00:00 +02:00
return;
}
2014-05-11 22:00:00 +02:00
if( c == 2 ) SV_ChangeLevel( false, Cmd_Argv( 1 ), NULL );
else SV_ChangeLevel( true, Cmd_Argv( 1 ), Cmd_Argv( 2 ));
2007-06-21 22:00:00 +02:00
}
2007-11-17 22:00:00 +01:00
/*
==================
SV_Restart_f
restarts current level
==================
*/
void SV_Restart_f( void )
{
2012-12-16 21:00:00 +01:00
if( sv.state != ss_active )
return;
2007-11-17 22:00:00 +01:00
// just sending console command
2011-02-22 22:00:00 +01:00
if( sv.background )
{
Cbuf_AddText( va( "map_background %s\n", sv.name ));
}
else
{
Cbuf_AddText( va( "map %s\n", sv.name ));
}
2007-11-17 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
2012-12-16 21:00:00 +01:00
/*
==================
SV_Reload_f
continue from latest savedgame
==================
*/
2009-09-28 22:00:00 +02:00
void SV_Reload_f( void )
{
const char *save;
string loadname;
2011-02-22 22:00:00 +01:00
if( sv.state != ss_active || sv.background )
2010-03-25 22:00:00 +01:00
return;
2009-09-28 22:00:00 +02:00
save = SV_GetLatestSave();
2012-12-16 21:00:00 +01:00
2009-09-28 22:00:00 +02:00
if( save )
{
FS_FileBase( save, loadname );
Cbuf_AddText( va( "load %s\n", loadname ));
}
else Cbuf_AddText( "newgame\n" ); // begin new game
}
2007-06-21 22:00:00 +02:00
/*
==================
SV_Kick_f
Kick a user off of the server
==================
*/
2007-11-17 22:00:00 +01:00
void SV_Kick_f( void )
2007-06-21 22:00:00 +02:00
{
2009-09-17 22:00:00 +02:00
if( Cmd_Argc() != 2 )
2007-06-21 22:00:00 +02:00
{
2009-09-17 22:00:00 +02:00
Msg( "Usage: kick <userid>\n" );
2007-06-21 22:00:00 +02:00
return;
}
2011-02-22 22:00:00 +01:00
if( !svs.clients || sv.background )
2007-06-21 22:00:00 +02:00
{
2009-09-17 22:00:00 +02:00
Msg( "^3no server running.\n" );
2007-06-21 22:00:00 +02:00
return;
}
2011-02-22 22:00:00 +01:00
2010-06-20 22:00:00 +02:00
if( !SV_SetPlayer( )) return;
2007-06-21 22:00:00 +02:00
2011-04-08 22:00:00 +02:00
SV_BroadcastPrintf( PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "You were kicked from the game\n" );
SV_DropClient( svs.currentPlayer );
2010-06-20 22:00:00 +02:00
// min case there is a funny zombie
2011-04-08 22:00:00 +02:00
svs.currentPlayer->lastmessage = host.realtime;
2007-06-21 22:00:00 +02:00
}
2009-11-25 22:00:00 +01:00
/*
==================
SV_Kill_f
==================
*/
void SV_Kill_f( void )
{
2014-01-01 21:00:00 +01:00
if( !SV_SetPlayer() || sv.background )
return;
2010-12-26 22:00:00 +01:00
2011-04-08 22:00:00 +02:00
if( !svs.currentPlayer || !SV_IsValidEdict( svs.currentPlayer->edict ))
return;
if( svs.currentPlayer->edict->v.health <= 0.0f )
2009-11-25 22:00:00 +01:00
{
2011-04-08 22:00:00 +02:00
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "Can't suicide -- allready dead!\n");
2009-11-25 22:00:00 +01:00
return;
}
2011-04-08 22:00:00 +02:00
svgame.dllFuncs.pfnClientKill( svs.currentPlayer->edict );
2009-11-25 22:00:00 +01:00
}
2010-04-07 22:00:00 +02:00
/*
==================
SV_EntPatch_f
==================
*/
void SV_EntPatch_f( void )
{
const char *mapname;
if( Cmd_Argc() < 2 )
{
if( sv.state != ss_dead )
{
mapname = sv.name;
}
else
{
Msg( "Usage: entpatch <mapname>\n" );
return;
}
}
2010-06-08 22:00:00 +02:00
else mapname = Cmd_Argv( 1 );
2010-04-07 22:00:00 +02:00
SV_WriteEntityPatch( mapname );
}
2007-06-21 22:00:00 +02:00
/*
================
SV_Status_f
================
*/
2007-11-17 22:00:00 +01:00
void SV_Status_f( void )
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
int i;
2008-07-09 22:00:00 +02:00
sv_client_t *cl;
2007-11-17 22:00:00 +01:00
2011-02-22 22:00:00 +01:00
if( !svs.clients || sv.background )
2007-06-21 22:00:00 +02:00
{
2011-04-05 22:00:00 +02:00
Msg( "^3no server running.\n" );
2007-06-21 22:00:00 +02:00
return;
}
2009-09-14 22:00:00 +02:00
Msg( "map: %s\n", sv.name );
Msg( "num score ping name lastmsg address port \n" );
Msg( "--- ----- ------- --------------- ------- --------------------- ------\n" );
2007-11-17 22:00:00 +01:00
2009-09-25 22:00:00 +02:00
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
int j, l, ping;
char *s;
2008-07-12 22:00:00 +02:00
if( !cl->state ) continue;
2007-06-21 22:00:00 +02:00
2009-09-16 22:00:00 +02:00
Msg( "%3i ", i );
2009-09-17 22:00:00 +02:00
Msg( "%5i ", (int)cl->edict->v.frags );
2007-11-17 22:00:00 +01:00
2009-09-14 22:00:00 +02:00
if( cl->state == cs_connected ) Msg( "Connect" );
else if( cl->state == cs_zombie ) Msg( "Zombie " );
2011-03-01 22:00:00 +01:00
else if( cl->fakeclient ) Msg( "Bot " );
2007-06-21 22:00:00 +02:00
else
{
ping = cl->ping < 9999 ? cl->ping : 9999;
2009-09-14 22:00:00 +02:00
Msg( "%7i ", ping );
2007-06-21 22:00:00 +02:00
}
2009-09-14 22:00:00 +02:00
Msg( "%s", cl->name );
2011-03-09 22:00:00 +01:00
l = 24 - Q_strlen( cl->name );
2009-09-16 22:00:00 +02:00
for( j = 0; j < l; j++ ) Msg( " " );
2010-10-09 22:00:00 +02:00
Msg( "%g ", ( host.realtime - cl->lastmessage ));
2010-10-07 22:00:00 +02:00
s = NET_BaseAdrToString( cl->netchan.remote_address );
2009-09-14 22:00:00 +02:00
Msg( "%s", s );
2011-03-09 22:00:00 +01:00
l = 22 - Q_strlen( s );
2009-09-14 22:00:00 +02:00
for( j = 0; j < l; j++ ) Msg( " " );
Msg( "%5i", cl->netchan.qport );
Msg( "\n" );
2007-06-21 22:00:00 +02:00
}
2009-09-14 22:00:00 +02:00
Msg( "\n" );
2007-06-21 22:00:00 +02:00
}
/*
==================
SV_ConSay_f
==================
*/
2007-11-17 22:00:00 +01:00
void SV_ConSay_f( void )
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
char *p, text[MAX_SYSPATH];
2008-07-09 22:00:00 +02:00
sv_client_t *client;
2007-11-17 22:00:00 +01:00
int i;
2007-06-21 22:00:00 +02:00
2011-02-22 22:00:00 +01:00
if( Cmd_Argc() < 2 ) return;
2007-06-21 22:00:00 +02:00
2014-01-01 21:00:00 +01:00
if( !svs.clients || sv.background )
2012-12-16 21:00:00 +01:00
{
Msg( "^3no server running.\n" );
return;
}
2011-03-09 22:00:00 +01:00
Q_strncpy( text, "console: ", MAX_SYSPATH );
2007-06-21 22:00:00 +02:00
p = Cmd_Args();
2009-06-24 22:00:00 +02:00
if( *p == '"' )
2007-06-21 22:00:00 +02:00
{
p++;
2011-03-09 22:00:00 +01:00
p[Q_strlen(p) - 1] = 0;
2007-06-21 22:00:00 +02:00
}
2012-12-16 21:00:00 +01:00
2011-03-09 22:00:00 +01:00
Q_strncat( text, p, MAX_SYSPATH );
2007-06-21 22:00:00 +02:00
2009-09-25 22:00:00 +02:00
for( i = 0, client = svs.clients; i < sv_maxclients->integer; i++, client++ )
2007-06-21 22:00:00 +02:00
{
2012-12-16 21:00:00 +01:00
if( client->state != cs_spawned )
continue;
2009-06-24 22:00:00 +02:00
SV_ClientPrintf( client, PRINT_CHAT, "%s\n", text );
2007-06-21 22:00:00 +02:00
}
}
/*
==================
SV_Heartbeat_f
==================
*/
2010-04-12 22:00:00 +02:00
void SV_Heartbeat_f( void )
2007-06-21 22:00:00 +02:00
{
2008-06-30 22:00:00 +02:00
svs.last_heartbeat = MAX_HEARTBEAT;
2007-06-21 22:00:00 +02:00
}
/*
===========
2007-11-17 22:00:00 +01:00
SV_ServerInfo_f
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
Examine serverinfo string
2007-06-21 22:00:00 +02:00
===========
*/
2007-11-17 22:00:00 +01:00
void SV_ServerInfo_f( void )
2007-06-21 22:00:00 +02:00
{
2009-11-10 22:00:00 +01:00
Msg( "Server info settings:\n" );
Info_Print( Cvar_Serverinfo( ));
2007-06-21 22:00:00 +02:00
}
/*
===========
2007-11-17 22:00:00 +01:00
SV_ClientInfo_f
2007-06-21 22:00:00 +02:00
Examine all a users info strings
===========
*/
2007-11-17 22:00:00 +01:00
void SV_ClientInfo_f( void )
2007-06-21 22:00:00 +02:00
{
2010-07-19 22:00:00 +02:00
if( Cmd_Argc() != 2 )
2007-06-21 22:00:00 +02:00
{
2010-07-19 22:00:00 +02:00
Msg( "Usage: clientinfo <userid>\n" );
2007-06-21 22:00:00 +02:00
return;
}
2010-07-19 22:00:00 +02:00
if( !SV_SetPlayer( )) return;
Msg( "userinfo\n" );
Msg( "--------\n" );
2011-04-08 22:00:00 +02:00
Info_Print( svs.currentPlayer->userinfo );
2007-07-21 22:00:00 +02:00
2007-06-21 22:00:00 +02:00
}
/*
===============
SV_KillServer_f
Kick everyone off, possibly in preparation for a new game
===============
*/
2010-01-30 22:00:00 +01:00
void SV_KillServer_f( void )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
if( !svs.initialized ) return;
2011-04-08 22:00:00 +02:00
Q_strncpy( host.finalmsg, "Server was killed", MAX_STRING );
2007-11-21 22:00:00 +01:00
SV_Shutdown( false );
2010-01-30 22:00:00 +01:00
NET_Config ( false ); // close network sockets
2007-06-21 22:00:00 +02:00
}
2010-04-12 22:00:00 +02:00
/*
===============
SV_PlayersOnly_f
disable plhysics but players
===============
*/
void SV_PlayersOnly_f( void )
{
2010-07-29 22:00:00 +02:00
if( !Cvar_VariableInteger( "sv_cheats" )) return;
2010-04-12 22:00:00 +02:00
sv.hostflags = sv.hostflags ^ SVF_PLAYERSONLY;
2010-07-29 22:00:00 +02:00
2010-10-09 22:00:00 +02:00
if(!( sv.hostflags & SVF_PLAYERSONLY ))
2011-10-09 22:00:00 +02:00
SV_BroadcastPrintf( D_INFO, "Resume server physic\n" );
else SV_BroadcastPrintf( D_INFO, "Freeze server physic\n" );
2010-04-12 22:00:00 +02:00
}
2012-12-16 21:00:00 +01:00
/*
===============
SV_EdictsInfo_f
===============
*/
2011-03-19 22:00:00 +01:00
void SV_EdictsInfo_f( void )
{
int active;
2011-04-06 22:00:00 +02:00
if( sv.state != ss_active )
{
Msg( "^3no server running.\n" );
return;
}
2011-03-19 22:00:00 +01:00
active = pfnNumberOfEntities();
Msg( "%5i edicts is used\n", active );
Msg( "%5i edicts is free\n", svgame.globals->maxEntities - active );
Msg( "%5i total\n", svgame.globals->maxEntities );
}
2012-12-16 21:00:00 +01:00
/*
===============
SV_EntityInfo_f
===============
*/
2011-11-13 21:00:00 +01:00
void SV_EntityInfo_f( void )
{
edict_t *ent;
int i;
if( sv.state != ss_active )
{
Msg( "^3no server running.\n" );
return;
}
for( i = 0; i < svgame.numEntities; i++ )
{
ent = EDICT_NUM( i );
if( !SV_IsValidEdict( ent )) continue;
Msg( "%5i origin: %.f %.f %.f", i, ent->v.origin[0], ent->v.origin[1], ent->v.origin[2] );
if( ent->v.classname )
Msg( ", class: %s", STRING( ent->v.classname ));
if( ent->v.globalname )
Msg( ", global: %s", STRING( ent->v.globalname ));
if( ent->v.targetname )
Msg( ", name: %s", STRING( ent->v.targetname ));
if( ent->v.target )
Msg( ", target: %s", STRING( ent->v.target ));
if( ent->v.model )
Msg( ", model: %s", STRING( ent->v.model ));
Msg( "\n" );
}
}
2007-06-21 22:00:00 +02:00
/*
==================
SV_InitOperatorCommands
==================
*/
2007-11-17 22:00:00 +01:00
void SV_InitOperatorCommands( void )
2007-06-21 22:00:00 +02:00
{
2008-11-14 22:00:00 +01:00
Cmd_AddCommand( "heartbeat", SV_Heartbeat_f, "send a heartbeat to the master server" );
Cmd_AddCommand( "kick", SV_Kick_f, "kick a player off the server by number or name" );
2009-11-25 22:00:00 +01:00
Cmd_AddCommand( "kill", SV_Kill_f, "die instantly" );
2008-11-14 22:00:00 +01:00
Cmd_AddCommand( "status", SV_Status_f, "print server status information" );
Cmd_AddCommand( "serverinfo", SV_ServerInfo_f, "print server settings" );
Cmd_AddCommand( "clientinfo", SV_ClientInfo_f, "print user infostring (player num required)" );
2010-10-09 22:00:00 +02:00
Cmd_AddCommand( "playersonly", SV_PlayersOnly_f, "freezes time, except for players" );
2008-11-14 22:00:00 +01:00
Cmd_AddCommand( "map", SV_Map_f, "start new level" );
2014-05-17 22:00:00 +02:00
Cmd_AddCommand( "newgame", SV_NewGame_f, "begin new game" );
Cmd_AddCommand( "endgame", SV_EndGame_f, "end current game" );
Cmd_AddCommand( "killgame", SV_KillGame_f, "end current game" );
2010-07-29 22:00:00 +02:00
Cmd_AddCommand( "hazardcourse", SV_HazardCourse_f, "starting a Hazard Course" );
2008-11-14 22:00:00 +01:00
Cmd_AddCommand( "changelevel", SV_ChangeLevel_f, "changing level" );
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
2009-09-28 22:00:00 +02:00
Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" );
2010-04-07 22:00:00 +02:00
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
2011-03-19 22:00:00 +01:00
Cmd_AddCommand( "edicts_info", SV_EdictsInfo_f, "show info about edicts" );
2011-11-13 21:00:00 +01:00
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
2008-07-17 22:00:00 +02:00
2008-07-11 22:00:00 +02:00
if( host.type == HOST_DEDICATED )
2007-11-17 22:00:00 +01:00
{
2008-11-14 22:00:00 +01:00
Cmd_AddCommand( "say", SV_ConSay_f, "send a chat message to everyone on the server" );
2011-04-08 22:00:00 +02:00
Cmd_AddCommand( "killserver", SV_KillServer_f, "shutdown current server" );
2007-11-17 22:00:00 +01:00
}
2012-05-14 22:00:00 +02:00
else
{
Cmd_AddCommand( "map_background", SV_MapBackground_f, "set background map" );
Cmd_AddCommand( "save", SV_Save_f, "save the game to a file" );
Cmd_AddCommand( "load", SV_Load_f, "load a saved game file" );
Cmd_AddCommand( "savequick", SV_QuickSave_f, "save the game to the quicksave" );
Cmd_AddCommand( "loadquick", SV_QuickLoad_f, "load a quick-saved game file" );
Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" );
Cmd_AddCommand( "autosave", SV_AutoSave_f, "save the game to 'autosave' file" );
}
2007-06-21 22:00:00 +02:00
}
2012-12-16 21:00:00 +01:00
/*
==================
SV_KillOperatorCommands
==================
*/
2007-11-17 22:00:00 +01:00
void SV_KillOperatorCommands( void )
{
2009-01-09 22:00:00 +01:00
Cmd_RemoveCommand( "heartbeat" );
Cmd_RemoveCommand( "kick" );
2009-11-25 22:00:00 +01:00
Cmd_RemoveCommand( "kill" );
2009-01-09 22:00:00 +01:00
Cmd_RemoveCommand( "status" );
Cmd_RemoveCommand( "serverinfo" );
Cmd_RemoveCommand( "clientinfo" );
2010-04-12 22:00:00 +02:00
Cmd_RemoveCommand( "playersonly" );
2009-01-09 22:00:00 +01:00
Cmd_RemoveCommand( "map" );
Cmd_RemoveCommand( "newgame" );
2014-05-17 22:00:00 +02:00
Cmd_RemoveCommand( "endgame" );
2012-12-16 21:00:00 +01:00
Cmd_RemoveCommand( "killgame" );
2010-07-29 22:00:00 +02:00
Cmd_RemoveCommand( "hazardcourse" );
2009-01-09 22:00:00 +01:00
Cmd_RemoveCommand( "changelevel" );
Cmd_RemoveCommand( "restart" );
2009-09-28 22:00:00 +02:00
Cmd_RemoveCommand( "reload" );
2010-04-07 22:00:00 +02:00
Cmd_RemoveCommand( "entpatch" );
2011-03-19 22:00:00 +01:00
Cmd_RemoveCommand( "edicts_info" );
2011-11-13 21:00:00 +01:00
Cmd_RemoveCommand( "entity_info" );
2007-11-17 22:00:00 +01:00
2008-07-11 22:00:00 +02:00
if( host.type == HOST_DEDICATED )
2007-11-17 22:00:00 +01:00
{
2009-01-09 22:00:00 +01:00
Cmd_RemoveCommand( "say" );
2011-04-08 22:00:00 +02:00
Cmd_RemoveCommand( "killserver" );
2007-11-17 22:00:00 +01:00
}
2012-05-14 22:00:00 +02:00
else
{
Cmd_RemoveCommand( "map_background" );
Cmd_RemoveCommand( "save" );
Cmd_RemoveCommand( "load" );
Cmd_RemoveCommand( "savequick" );
Cmd_RemoveCommand( "loadquick" );
Cmd_RemoveCommand( "killsave" );
Cmd_RemoveCommand( "autosave" );
}
2007-11-17 22:00:00 +01:00
}