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

530 lines
11 KiB
C
Raw Normal View History

2007-11-17 22:00:00 +01:00
//=======================================================================
// Copyright XashXT Group 2007 <20>
// sv_cmds.c - server console commands
//=======================================================================
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"
/*
====================
SV_SetMaster_f
Specify a list of master servers
====================
*/
2007-11-17 22:00:00 +01:00
void SV_SetMaster_f( void )
2007-06-21 22:00:00 +02:00
{
int i, slot;
// only dedicated servers send heartbeats
2007-11-17 22:00:00 +01:00
if(!dedicated->value)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Only dedicated servers use masters.\n");
2007-06-21 22:00:00 +02:00
return;
}
// make sure the server is listed public
Cvar_Set ("public", "1");
2007-11-17 22:00:00 +01:00
for (i = 1; i < MAX_MASTERS; i++)
{
memset(&master_adr[i], 0, sizeof(master_adr[i]));
}
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
// slot 0 will always contain the id master
for (i = 1, slot = 1; i < Cmd_Argc(); i++)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
if (slot == MAX_MASTERS) break;
2007-06-21 22:00:00 +02:00
if (!NET_StringToAdr (Cmd_Argv(i), &master_adr[i]))
{
2007-07-28 22:00:00 +02:00
Msg ("Bad address: %s\n", Cmd_Argv(i));
2007-06-21 22:00:00 +02:00
continue;
}
2007-11-17 22:00:00 +01:00
if(!master_adr[slot].port) master_adr[slot].port = BigShort (PORT_MASTER);
2007-07-28 22:00:00 +02:00
Msg ("Master server at %s\n", NET_AdrToString (master_adr[slot]));
Msg ("Sending a ping.\n");
2007-06-21 22:00:00 +02:00
Netchan_OutOfBandPrint (NS_SERVER, master_adr[slot], "ping");
slot++;
}
2007-09-09 22:00:00 +02:00
svs.last_heartbeat = -99999.0f;
2007-06-21 22:00:00 +02:00
}
/*
==================
SV_SetPlayer
Sets sv_client and sv_player to the player with idnum Cmd_Argv(1)
==================
*/
2007-11-17 22:00:00 +01:00
bool SV_SetPlayer( void )
2007-06-21 22:00:00 +02:00
{
char *s;
2007-11-17 22:00:00 +01:00
client_state_t *cl;
int i, idnum;
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() < 2) return false;
2007-06-21 22:00:00 +02:00
s = Cmd_Argv(1);
// numeric values are just slot numbers
if (s[0] >= '0' && s[0] <= '9')
{
idnum = atoi(Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
if (idnum < 0 || idnum >= maxclients->integer)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Bad client slot: %i\n", idnum);
2007-06-21 22:00:00 +02:00
return false;
}
sv_client = &svs.clients[idnum];
sv_player = sv_client->edict;
if (!sv_client->state)
{
2007-11-17 22:00:00 +01: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
2007-11-17 22:00:00 +01:00
for (i = 0, cl = svs.clients; i < maxclients->integer; i++, cl++)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
if (!cl->state) continue;
2007-06-21 22:00:00 +02:00
if (!strcmp(cl->name, s))
{
sv_client = cl;
sv_player = sv_client->edict;
return true;
}
}
2007-07-28 22:00:00 +02:00
Msg ("Userid %s is not on the server\n", s);
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
{
2007-11-17 22:00:00 +01:00
char filename[MAX_QPATH];
if(Cmd_Argc() != 2)
2007-10-19 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Usage: map <filename>\n");
2007-10-19 22:00:00 +02:00
return;
}
2007-11-30 22:00:00 +01:00
com.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
if(!FS_FileExists(va("maps/%s", filename )))
{
Msg("Can't loading %s\n", filename );
return;
}
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
SV_InitGame(); // reset previous state
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
SV_BroadcastCommand("changing\n");
SV_SendClientMessages();
2008-05-22 22:00:00 +02:00
SV_SpawnServer( filename, NULL, ss_active );
2007-11-17 22:00:00 +01:00
SV_BroadcastCommand ("reconnect\n");
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
// archive server state
2007-11-30 22:00:00 +01:00
com.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
2007-11-17 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
/*
==================
2007-11-17 22:00:00 +01:00
SV_Movie_f
2007-06-21 22:00:00 +02:00
2008-05-18 22:00:00 +02:00
Playing a Darkplaces video with specified name
2007-06-21 22:00:00 +02:00
==================
*/
2007-11-17 22:00:00 +01:00
void SV_Movie_f( void )
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
char filename[MAX_QPATH];
2007-09-02 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() != 2)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Usage: movie <filename>\n");
return;
2007-09-02 22:00:00 +02:00
}
2007-09-06 22:00:00 +02:00
2007-11-30 22:00:00 +01:00
com.snprintf( filename, MAX_QPATH, "%s.roq", Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
if(!FS_FileExists(va("video/%s", filename )))
{
Msg("Can't loading %s\n", filename );
return;
}
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
SV_InitGame();
SV_BroadcastCommand( "changing\n" );
SV_SpawnServer( filename, NULL, ss_cinematic );
SV_BroadcastCommand( "reconnect\n" );
}
2007-06-21 22:00:00 +02:00
2008-01-20 22:00:00 +01:00
void SV_Newgame_f( void )
{
// FIXME: do some clear operations
2008-05-20 22:00:00 +02:00
// FIXME: parse newgame script
2008-01-20 22:00:00 +01:00
Cbuf_ExecuteText(EXEC_APPEND, va("map %s\n", GI->startmap ));
}
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
{
2007-11-17 22:00:00 +01:00
char filename[MAX_QPATH];
if(Cmd_Argc() != 2)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg ("Usage: load <filename>\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-30 22:00:00 +01:00
com.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
if(!FS_FileExists(va("save/%s", filename )))
{
Msg("Can't loading %s\n", filename );
return;
}
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
SV_ReadSaveFile( filename );
SV_BroadcastCommand( "changing\n" );
2008-05-22 22:00:00 +02:00
SV_SpawnServer( svs.mapcmd, filename, ss_active );
2007-11-17 22:00:00 +01:00
SV_BroadcastCommand( "reconnect\n" );
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
{
2007-11-17 22:00:00 +01:00
char filename[MAX_QPATH];
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() != 2)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg ("Usage: savegame <directory>\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-30 22:00:00 +01:00
com.snprintf( filename, MAX_QPATH, "%s.bin", Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
SV_WriteSaveFile( filename );
}
/*
==================
SV_ChangeLevel_f
Saves the state of the map just being exited and goes to a new map.
==================
*/
void SV_ChangeLevel_f( void )
{
char filename[MAX_QPATH];
2008-06-09 22:00:00 +02:00
int c = Cmd_Argc();
2007-11-17 22:00:00 +01:00
2008-06-09 22:00:00 +02:00
if( c != 2 && c != 3 )
2007-06-21 22:00:00 +02:00
{
2008-06-09 22:00:00 +02:00
Msg ("Usage: changelevel <map> [landmark]\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-30 22:00:00 +01:00
com.snprintf( filename, MAX_QPATH, "%s.bsp", Cmd_Argv(1));
2007-11-17 22:00:00 +01:00
if(!FS_FileExists(va("maps/%s", filename )))
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Can't loading %s\n", filename );
2007-06-21 22:00:00 +02:00
return;
}
2008-05-22 22:00:00 +02:00
if(sv.state == ss_active)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
bool *savedFree;
client_state_t *cl;
int i;
// clear all the client free flags before saving so that
// when the level is re-entered, the clients will spawn
// at spawn points instead of occupying body shells
savedFree = Z_Malloc(maxclients->integer * sizeof(bool));
for (i = 0, cl = svs.clients; i < maxclients->integer; i++, cl++)
{
savedFree[i] = cl->edict->priv.sv->free;
cl->edict->priv.sv->free = true;
}
SV_WriteSaveFile( "save0.bin" ); // autosave
// we must restore these for clients to transfer over correctly
for (i = 0, cl = svs.clients; i < maxclients->integer; i++, cl++)
cl->edict->priv.sv->free = savedFree[i];
2008-05-22 22:00:00 +02:00
Mem_Free(savedFree);
2007-06-21 22:00:00 +02:00
}
2007-11-17 22:00:00 +01:00
SV_InitGame(); // reset previous state
SV_BroadcastCommand("changing\n");
SV_SendClientMessages();
2008-05-22 22:00:00 +02:00
SV_SpawnServer( filename, NULL, ss_active );
2007-11-17 22:00:00 +01:00
SV_BroadcastCommand ("reconnect\n");
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
// archive server state
2007-11-30 22:00:00 +01:00
com.strncpy (svs.mapcmd, filename, sizeof(svs.mapcmd) - 1);
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 )
{
char filename[MAX_QPATH];
2008-05-22 22:00:00 +02:00
if(sv.state != ss_active) return;
2007-11-17 22:00:00 +01:00
strncpy( filename, svs.mapcmd, MAX_QPATH );
FS_StripExtension( filename );
// just sending console command
Cbuf_AddText(va("map %s\n", filename ));
}
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
{
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() != 2)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg ("Usage: kick <userid>\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-17 22:00:00 +01:00
if(!svs.clients)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("^3no server running.\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-17 22:00:00 +01:00
if(!SV_SetPlayer()) return;
2007-06-21 22:00:00 +02:00
2008-06-09 22:00:00 +02:00
SV_BroadcastPrintf (PRINT_CONSOLE, "%s was kicked\n", sv_client->name);
SV_ClientPrintf(sv_client, PRINT_CONSOLE, "You were kicked from the game\n");
2007-11-17 22:00:00 +01:00
SV_DropClient(sv_client);
sv_client->lastmessage = svs.realtime; // min case there is a funny zombie
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;
2007-11-04 22:00:00 +01:00
client_state_t *cl;
2007-11-17 22:00:00 +01:00
if(!svs.clients)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg ("^3no server running.\n");
2007-06-21 22:00:00 +02:00
return;
}
2007-11-17 22:00:00 +01:00
Msg("map: %s\n", sv.name);
Msg("num score ping name lastmsg address port \n");
Msg("--- ----- ------- --------------- ------- --------------------- ------\n");
for(i = 0, cl = svs.clients; i < 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;
2007-07-22 22:00:00 +02:00
if (!cl->state) continue;
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
Msg("%3i ", i);
Msg("%5i ", cl->edict->priv.sv->client->ps.stats[STAT_FRAGS]);
if (cl->state == cs_connected) Msg("Connect");
else if (cl->state == cs_zombie) Msg ("Zombie ");
2007-06-21 22:00:00 +02:00
else
{
ping = cl->ping < 9999 ? cl->ping : 9999;
2007-11-17 22:00:00 +01:00
Msg("%7i ", ping);
2007-06-21 22:00:00 +02:00
}
2007-11-17 22:00:00 +01:00
Msg("%s", cl->name );
2007-11-30 22:00:00 +01:00
l = 16 - com.strlen(cl->name);
2007-11-17 22:00:00 +01:00
for (j = 0; j < l; j++) Msg (" ");
Msg ("%.5f ", svs.realtime - cl->lastmessage );
2007-06-21 22:00:00 +02:00
s = NET_AdrToString ( cl->netchan.remote_address);
2007-07-28 22:00:00 +02:00
Msg ("%s", s);
2007-06-21 22:00:00 +02:00
l = 22 - strlen(s);
2007-11-17 22:00:00 +01:00
for (j = 0; j < l; j++) Msg (" ");
Msg("%5i", cl->netchan.qport);
Msg("\n");
2007-06-21 22:00:00 +02:00
}
2007-07-28 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];
client_state_t *client;
int i;
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() < 2) return;
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
strncpy(text, "console: ", MAX_SYSPATH );
2007-06-21 22:00:00 +02:00
p = Cmd_Args();
2007-11-17 22:00:00 +01:00
if(*p == '"')
2007-06-21 22:00:00 +02:00
{
p++;
2007-11-30 22:00:00 +01:00
p[com.strlen(p) - 1] = 0;
2007-06-21 22:00:00 +02:00
}
2007-11-30 22:00:00 +01:00
com.strncat(text, p, MAX_SYSPATH );
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
for (i = 0, client = svs.clients; i < maxclients->integer; i++, client++)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
if (client->state != cs_spawned) continue;
SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text );
2007-06-21 22:00:00 +02:00
}
}
/*
==================
SV_Heartbeat_f
==================
*/
void SV_Heartbeat_f (void)
{
2007-09-09 22:00:00 +02:00
svs.last_heartbeat = -99999.0f;
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
{
2007-11-17 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
{
2007-11-17 22:00:00 +01:00
if(Cmd_Argc() != 2)
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
Msg("Usage: clientinfo <userid>\n" );
2007-06-21 22:00:00 +02:00
return;
}
2007-11-17 22:00:00 +01:00
if(!SV_SetPlayer()) return;
Msg("userinfo\n");
Msg("--------\n");
Info_Print( sv_client->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
===============
*/
void SV_KillServer_f (void)
{
2007-11-17 22:00:00 +01:00
if(!svs.initialized) return;
2007-11-30 22:00:00 +01:00
com.strncpy( host.finalmsg, "Server was killed\n", MAX_STRING );
2007-11-21 22:00:00 +01:00
SV_Shutdown( false );
2007-11-17 22:00:00 +01:00
NET_Config( false );// close network sockets
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
{
2007-11-17 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" );
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)" );
Cmd_AddCommand("map", SV_Map_f, "start new level" );
2008-01-20 22:00:00 +01:00
Cmd_AddCommand("newgame", SV_Newgame_f, "begin new game" );
2007-11-17 22:00:00 +01:00
Cmd_AddCommand("movie", SV_Movie_f, "playing video file" );
Cmd_AddCommand("changelevel", SV_ChangeLevel_f, "changing level" );
Cmd_AddCommand("restart", SV_Restart_f, "restarting current level" );
2008-01-17 22:00:00 +01:00
Cmd_AddCommand("sectorlist", SV_SectorList_f, "display pvs sectors" );
2007-11-17 22:00:00 +01:00
if( dedicated->value )
{
Cmd_AddCommand ("say", SV_ConSay_f, "send a chat message to everyone on the server" );
Cmd_AddCommand("setmaster", SV_SetMaster_f, "set ip address for dedicated server" );
}
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 ("killserver", SV_KillServer_f, "shutdown current server" );
2007-06-21 22:00:00 +02:00
}
2007-11-17 22:00:00 +01:00
void SV_KillOperatorCommands( void )
{
Cmd_RemoveCommand("heartbeat");
Cmd_RemoveCommand("kick");
Cmd_RemoveCommand("status");
Cmd_RemoveCommand("serverinfo");
Cmd_RemoveCommand("clientinfo");
Cmd_RemoveCommand("map");
Cmd_RemoveCommand("movie");
2008-01-20 22:00:00 +01:00
Cmd_RemoveCommand("newgame");
2007-11-17 22:00:00 +01:00
Cmd_RemoveCommand("changelevel");
Cmd_RemoveCommand("restart");
2008-01-17 22:00:00 +01:00
Cmd_RemoveCommand("sectorlist");
2007-11-17 22:00:00 +01:00
2008-05-20 22:00:00 +02:00
if( dedicated->integer )
2007-11-17 22:00:00 +01:00
{
Cmd_RemoveCommand("say");
Cmd_RemoveCommand("setmaster");
}
Cmd_RemoveCommand("save");
Cmd_RemoveCommand("load");
Cmd_RemoveCommand("killserver");
}