2009-02-28 14:41:18 +00:00
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
|
|
|
* 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 2 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.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*
|
|
|
|
* Server commands received by clients. There are only two ways on which
|
|
|
|
* those can be received. Typed via stdin into the server console or via
|
|
|
|
* a network / internal communication datagram.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*/
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 15:46:36 +00:00
|
|
|
#include "header/server.h"
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Specify a list of master servers
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_SetMaster_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
int i, slot;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* only dedicated servers send heartbeats */
|
|
|
|
if ( !dedicated->value )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Only dedicated servers use masters.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* make sure the server is listed public */
|
|
|
|
Cvar_Set( "public", "1" );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
for ( i = 1; i < MAX_MASTERS; i++ )
|
|
|
|
{
|
|
|
|
memset( &master_adr [ i ], 0, sizeof ( master_adr [ i ] ) );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
slot = 1; /* slot 0 will always contain the id master */
|
|
|
|
|
|
|
|
for ( i = 1; i < Cmd_Argc(); i++ )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( slot == MAX_MASTERS )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
break;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !NET_StringToAdr( Cmd_Argv( i ), &master_adr [ i ] ) )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Bad address: %s\n", Cmd_Argv( i ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( master_adr [ slot ].port == 0 )
|
|
|
|
{
|
|
|
|
master_adr [ slot ].port = BigShort( PORT_MASTER );
|
|
|
|
}
|
|
|
|
|
|
|
|
Com_Printf( "Master server at %s\n", NET_AdrToString( master_adr [ slot ] ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Sending a ping.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Netchan_OutOfBandPrint( NS_SERVER, master_adr [ slot ], "ping" );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
slot++;
|
|
|
|
}
|
|
|
|
|
|
|
|
svs.last_heartbeat = -9999999;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Sets sv_client and sv_player to the player with idnum Cmd_Argv(1)
|
|
|
|
*/
|
|
|
|
qboolean
|
|
|
|
SV_SetPlayer ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
client_t *cl;
|
|
|
|
int i;
|
|
|
|
int idnum;
|
|
|
|
char *s;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() < 2 )
|
|
|
|
{
|
|
|
|
return ( false );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
s = Cmd_Argv( 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* numeric values are just slot numbers */
|
|
|
|
if ( ( s [ 0 ] >= '0' ) && ( s [ 0 ] <= '9' ) )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
idnum = atoi( Cmd_Argv( 1 ) );
|
|
|
|
|
|
|
|
if ( ( idnum < 0 ) || ( idnum >= maxclients->value ) )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Bad client slot: %i\n", idnum );
|
|
|
|
return ( false );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
sv_client = &svs.clients [ idnum ];
|
2009-02-28 14:41:18 +00:00
|
|
|
sv_player = sv_client->edict;
|
2010-11-25 16:22:55 +00:00
|
|
|
|
|
|
|
if ( !sv_client->state )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Client %i is not active\n", idnum );
|
|
|
|
return ( false );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-11-25 16:22:55 +00:00
|
|
|
|
|
|
|
return ( true );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* check for a name match */
|
|
|
|
for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !cl->state )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( !strcmp( cl->name, s ) )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
|
|
|
sv_client = cl;
|
|
|
|
sv_player = sv_client->edict;
|
2010-11-25 16:22:55 +00:00
|
|
|
return ( true );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Userid %s is not on the server\n", s );
|
|
|
|
return ( false );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Puts the server in demo mode on a specific map/cinematic
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_DemoMap_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() != 2 )
|
2009-03-04 09:38:39 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "USAGE: demomap <demoname.dm2>\n" );
|
2009-03-04 09:38:39 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SV_Map( true, Cmd_Argv( 1 ), false );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* ==================
|
|
|
|
* SV_GameMap_f
|
|
|
|
*
|
|
|
|
* Saves the state of the map just being exited and goes to a new map.
|
|
|
|
*
|
|
|
|
* If the initial character of the map string is '*', the next map is
|
|
|
|
* in a new unit, so the current savegame directory is cleared of
|
|
|
|
* map files.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* inter.cin+jail
|
|
|
|
* Clears the archived maps, plays the inter.cin cinematic, then
|
|
|
|
* goes to map jail.bsp.
|
|
|
|
* ==================
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_GameMap_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
char *map;
|
|
|
|
int i;
|
|
|
|
client_t *cl;
|
|
|
|
qboolean *savedInuse;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() != 2 )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "USAGE: gamemap <map>\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_DPrintf( "SV_GameMap(%s)\n", Cmd_Argv( 1 ) );
|
|
|
|
|
|
|
|
FS_CreatePath( va( "%s/save/current/", FS_Gamedir() ) );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* check for clearing the current savegame */
|
|
|
|
map = Cmd_Argv( 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( map [ 0 ] == '*' )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
/* wipe all the *.sav files */
|
|
|
|
SV_WipeSavegame( "current" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
else
|
2010-11-25 16:22:55 +00:00
|
|
|
{
|
|
|
|
/* save the map just exited */
|
|
|
|
if ( sv.state == ss_game )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
/* clear all the client inuse flags before saving so that
|
|
|
|
when the level is re-entered, the clients will spawn
|
|
|
|
at spawn points instead of occupying body shells */
|
|
|
|
savedInuse = malloc( maxclients->value * sizeof ( qboolean ) );
|
|
|
|
|
|
|
|
for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
savedInuse [ i ] = cl->edict->inuse;
|
2009-02-28 14:41:18 +00:00
|
|
|
cl->edict->inuse = false;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
SV_WriteLevelFile();
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* we must restore these for clients to transfer over correctly */
|
|
|
|
for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
|
|
|
{
|
|
|
|
cl->edict->inuse = savedInuse [ i ];
|
|
|
|
}
|
|
|
|
|
|
|
|
free( savedInuse );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* start up the next map */
|
|
|
|
SV_Map( false, Cmd_Argv( 1 ), false );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* archive server state */
|
|
|
|
strncpy( svs.mapcmd, Cmd_Argv( 1 ), sizeof ( svs.mapcmd ) - 1 );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* copy off the level to the autosave slot */
|
|
|
|
if ( !dedicated->value )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
SV_WriteServerFile( true );
|
|
|
|
SV_CopySaveGame( "current", "save0" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Goes directly to a given map without any savegame archiving.
|
|
|
|
* For development work
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_Map_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
char *map;
|
|
|
|
char expanded [ MAX_QPATH ];
|
|
|
|
|
|
|
|
if ( Cmd_Argc() != 2 )
|
|
|
|
{
|
|
|
|
Com_Printf( "USAGE: map <mapname>\n" );
|
|
|
|
return;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* if not a pcx, demo, or cinematic, check to make sure the level exists */
|
|
|
|
map = Cmd_Argv( 1 );
|
2009-03-04 09:38:39 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !strstr( map, "." ) && !strstr( map, "$" ) && ( *map != '*' ) )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_sprintf( expanded, sizeof ( expanded ), "maps/%s.bsp", map );
|
2009-03-04 09:38:39 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( FS_LoadFile( expanded, NULL ) == -1 )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Can't find %s\n", expanded );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
sv.state = ss_dead; /* don't save current level when changing */
|
|
|
|
SV_WipeSavegame( "current" );
|
|
|
|
SV_GameMap_f();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Kick a user off of the server
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_Kick_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.initialized )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "No server running.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() != 2 )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Usage: kick <userid>\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !SV_SetPlayer() )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( ( sv_client->state == cs_spawned ) && *sv_client->name )
|
|
|
|
{
|
|
|
|
SV_BroadcastPrintf( PRINT_HIGH, "%s was kicked\n", sv_client->name );
|
|
|
|
}
|
2009-03-04 09:38:39 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* print directly, because the dropped client won't get the
|
|
|
|
SV_BroadcastPrintf message */
|
|
|
|
SV_ClientPrintf( sv_client, PRINT_HIGH, "You were kicked from the game\n" );
|
|
|
|
SV_DropClient( sv_client );
|
|
|
|
sv_client->lastmessage = svs.realtime; /* min case there is a funny zombie */
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
void
|
|
|
|
SV_Status_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
int i, j, l;
|
|
|
|
client_t *cl;
|
|
|
|
char *s;
|
|
|
|
int ping;
|
|
|
|
|
|
|
|
if ( !svs.clients )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "No server running.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "map : %s\n", sv.name );
|
|
|
|
|
|
|
|
Com_Printf( "num score ping name lastmsg address qport \n" );
|
|
|
|
Com_Printf( "--- ----- ---- --------------- ------- --------------------- ------\n" );
|
|
|
|
|
|
|
|
for ( i = 0, cl = svs.clients; i < maxclients->value; i++, cl++ )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !cl->state )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "%2i ", i );
|
|
|
|
Com_Printf( "%5i ", cl->edict->client->ps.stats [ STAT_FRAGS ] );
|
|
|
|
|
|
|
|
if ( cl->state == cs_connected )
|
|
|
|
{
|
|
|
|
Com_Printf( "CNCT " );
|
|
|
|
}
|
|
|
|
else if ( cl->state == cs_zombie )
|
|
|
|
{
|
|
|
|
Com_Printf( "ZMBI " );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ping = cl->ping < 9999 ? cl->ping : 9999;
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "%4i ", ping );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "%s", cl->name );
|
|
|
|
l = 16 - strlen( cl->name );
|
|
|
|
|
|
|
|
for ( j = 0; j < l; j++ )
|
|
|
|
{
|
|
|
|
Com_Printf( " " );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "%7i ", svs.realtime - cl->lastmessage );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
s = NET_AdrToString( cl->netchan.remote_address );
|
|
|
|
Com_Printf( "%s", s );
|
|
|
|
l = 22 - strlen( s );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
for ( j = 0; j < l; j++ )
|
|
|
|
{
|
|
|
|
Com_Printf( " " );
|
|
|
|
}
|
|
|
|
|
|
|
|
Com_Printf( "%5i", cl->netchan.qport );
|
|
|
|
|
|
|
|
Com_Printf( "\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-11-25 16:22:55 +00:00
|
|
|
|
|
|
|
Com_Printf( "\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
void
|
|
|
|
SV_ConSay_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
|
|
|
client_t *client;
|
2010-11-25 16:22:55 +00:00
|
|
|
int j;
|
|
|
|
char *p;
|
|
|
|
char text [ 1024 ];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() < 2 )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.initialized )
|
|
|
|
{
|
|
|
|
Com_Printf( "No server running.\n" );
|
2009-03-04 09:38:39 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-03-04 09:38:39 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
strcpy( text, "console: " );
|
2009-02-28 14:41:18 +00:00
|
|
|
p = Cmd_Args();
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( *p == '"' )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
|
|
|
p++;
|
2010-11-25 16:22:55 +00:00
|
|
|
p [ strlen( p ) - 1 ] = 0;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
strcat( text, p );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
for ( j = 0, client = svs.clients; j < maxclients->value; j++, client++ )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( client->state != cs_spawned )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SV_ClientPrintf( client, PRINT_CHAT, "%s\n", text );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
void
|
|
|
|
SV_Heartbeat_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
|
|
|
svs.last_heartbeat = -9999999;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Examine or change the serverinfo string
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_Serverinfo_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Server info settings:\n" );
|
|
|
|
Info_Print( Cvar_Serverinfo() );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Examine all a users info strings
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_DumpUser_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.initialized )
|
2009-03-04 09:38:39 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "No server running.\n" );
|
2009-03-04 09:38:39 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() != 2 )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Usage: info <userid>\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !SV_SetPlayer() )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "userinfo\n" );
|
|
|
|
Com_Printf( "--------\n" );
|
|
|
|
Info_Print( sv_client->userinfo );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Begins server demo recording. Every entity and every message will be
|
|
|
|
* recorded, but no playerinfo will be stored. Primarily for demo merging.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_ServerRecord_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
char name [ MAX_OSPATH ];
|
|
|
|
byte buf_data [ 32768 ];
|
|
|
|
sizebuf_t buf;
|
|
|
|
int len;
|
|
|
|
int i;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( Cmd_Argc() != 2 )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "serverrecord <demoname>\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( svs.demofile )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Already recording.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( sv.state != ss_game )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "You must be in a level to record.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( strstr( Cmd_Argv( 1 ), ".." ) || strstr( Cmd_Argv( 1 ), "/" ) || strstr( Cmd_Argv( 1 ), "\\" ) )
|
2009-03-04 09:38:39 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Illegal filename.\n" );
|
2009-03-04 09:38:39 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* open the demo file */
|
|
|
|
Com_sprintf( name, sizeof ( name ), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv( 1 ) );
|
2009-03-04 09:38:39 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "recording to %s.\n", name );
|
|
|
|
FS_CreatePath( name );
|
|
|
|
svs.demofile = fopen( name, "wb" );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.demofile )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "ERROR: couldn't open.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* setup a buffer to catch all multicasts */
|
|
|
|
SZ_Init( &svs.demo_multicast, svs.demo_multicast_buf, sizeof ( svs.demo_multicast_buf ) );
|
|
|
|
|
|
|
|
/* write a single giant fake message with all the startup info */
|
|
|
|
SZ_Init( &buf, buf_data, sizeof ( buf_data ) );
|
|
|
|
|
|
|
|
/* serverdata needs to go over for all types of servers
|
|
|
|
to make sure the protocol is right, and to set the gamedir */
|
|
|
|
MSG_WriteByte( &buf, svc_serverdata );
|
|
|
|
MSG_WriteLong( &buf, PROTOCOL_VERSION );
|
|
|
|
MSG_WriteLong( &buf, svs.spawncount );
|
|
|
|
|
|
|
|
/* 2 means server demo */
|
|
|
|
MSG_WriteByte( &buf, 2 ); /* demos are always attract loops */
|
|
|
|
MSG_WriteString( &buf, (char *) Cvar_VariableString( "gamedir" ) );
|
|
|
|
MSG_WriteShort( &buf, -1 );
|
|
|
|
|
|
|
|
/* send full levelname */
|
|
|
|
MSG_WriteString( &buf, sv.configstrings [ CS_NAME ] );
|
|
|
|
|
|
|
|
for ( i = 0; i < MAX_CONFIGSTRINGS; i++ )
|
|
|
|
{
|
|
|
|
if ( sv.configstrings [ i ] [ 0 ] )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
MSG_WriteByte( &buf, svc_configstring );
|
|
|
|
MSG_WriteShort( &buf, i );
|
|
|
|
MSG_WriteString( &buf, sv.configstrings [ i ] );
|
|
|
|
|
|
|
|
if ( buf.cursize + 67 >= buf.maxsize )
|
|
|
|
{
|
|
|
|
Com_Printf( "not enough buffer space available.\n" );
|
|
|
|
fclose( svs.demofile );
|
2009-03-04 09:38:39 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
/* write it to the demo file */
|
|
|
|
Com_DPrintf( "signon message length: %i\n", buf.cursize );
|
|
|
|
len = LittleLong( buf.cursize );
|
|
|
|
fwrite( &len, 4, 1, svs.demofile );
|
|
|
|
fwrite( buf.data, buf.cursize, 1, svs.demofile );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Ends server demo recording
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_ServerStop_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.demofile )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Not doing a serverrecord.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-11-25 16:22:55 +00:00
|
|
|
|
|
|
|
fclose( svs.demofile );
|
2009-02-28 14:41:18 +00:00
|
|
|
svs.demofile = NULL;
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "Recording completed.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Kick everyone off, possibly in preparation for a new game
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_KillServer_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !svs.initialized )
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2010-11-25 16:22:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SV_Shutdown( "Server was killed.\n", false );
|
|
|
|
NET_Config( false ); /* close network sockets */
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-11-25 16:22:55 +00:00
|
|
|
* Let the game dll handle a command
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
SV_ServerCommand_f ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
if ( !ge )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Com_Printf( "No game loaded.\n" );
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ge->ServerCommand();
|
|
|
|
}
|
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
void
|
|
|
|
SV_InitOperatorCommands ( void )
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "heartbeat", SV_Heartbeat_f );
|
|
|
|
Cmd_AddCommand( "kick", SV_Kick_f );
|
|
|
|
Cmd_AddCommand( "status", SV_Status_f );
|
|
|
|
Cmd_AddCommand( "serverinfo", SV_Serverinfo_f );
|
|
|
|
Cmd_AddCommand( "dumpuser", SV_DumpUser_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "map", SV_Map_f );
|
|
|
|
Cmd_AddCommand( "demomap", SV_DemoMap_f );
|
|
|
|
Cmd_AddCommand( "gamemap", SV_GameMap_f );
|
|
|
|
Cmd_AddCommand( "setmaster", SV_SetMaster_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if ( dedicated->value )
|
2010-11-25 16:22:55 +00:00
|
|
|
{
|
|
|
|
Cmd_AddCommand( "say", SV_ConSay_f );
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "serverrecord", SV_ServerRecord_f );
|
|
|
|
Cmd_AddCommand( "serverstop", SV_ServerStop_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "save", SV_Savegame_f );
|
|
|
|
Cmd_AddCommand( "load", SV_Loadgame_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "killserver", SV_KillServer_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-11-25 16:22:55 +00:00
|
|
|
Cmd_AddCommand( "sv", SV_ServerCommand_f );
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|