/* * Copyright(c) 1997-2001 Id Software, Inc. * Copyright(c) 2002 The Quakeforge Project. * Copyright(c) 2006 Quetoo. * * 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. */ #include "server.h" /* OPERATOR CONSOLE ONLY COMMANDS These commands can only be entered from stdin or by a remote operator datagram */ /* SV_SetMaster_f Specify a list of master servers */ void SV_SetMaster_f(void){ int i, slot; // only dedicated servers send heartbeats if(!dedicated->value){ Com_Printf("Only dedicated servers use masters.\n"); return; } // make sure the server is listed public Cvar_Set("public", "1"); for(i = 1; i < MAX_MASTERS; i++) memset(&master_adr[i], 0, sizeof(master_adr[i])); slot = 1; // slot 0 will always contain the id master for(i = 1; i < Cmd_Argc(); i++){ if(slot == MAX_MASTERS) break; if(!NET_StringToAdr(Cmd_Argv(i), &master_adr[i])){ Com_Printf("Bad address: %s\n", Cmd_Argv(i)); continue; } 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])); Com_Printf("Sending a ping.\n"); Netchan_OutOfBandPrint(NS_SERVER, master_adr[slot], "ping"); slot++; } svs.last_heartbeat = -9999999; } /* SV_SetPlayer Sets sv_client and sv_player to the player with idnum Cmd_Argv(1) */ qboolean SV_SetPlayer(void){ client_t *cl; int i; int idnum; char *s; if(Cmd_Argc() < 2) return false; s = Cmd_Argv(1); // numeric values are just slot numbers if(s[0] >= '0' && s[0] <= '9'){ idnum = atoi(Cmd_Argv(1)); if(idnum < 0 || idnum >= maxclients->value){ Com_Printf("Bad client slot: %i\n", idnum); return false; } sv_client = &svs.clients[idnum]; sv_player = sv_client->edict; if(!sv_client->state){ Com_Printf("Client %i is not active\n", idnum); return false; } return true; } // check for a name match for(i = 0, cl = svs.clients; i < maxclients->value; i++, cl++){ if(!cl->state) continue; if(!strcmp(cl->name, s)){ sv_client = cl; sv_player = sv_client->edict; return true; } } Com_Printf("Userid %s is not on the server\n", s); return false; } /* SV_Demo_f Starts playback of the specified demo file. */ void SV_Demo_f(void){ if(Cmd_Argc() != 2){ Com_Printf("Usage: demo \n"); return; } // start up the demo SV_Map(va("%s.dm2", Cmd_Argv(1))); } /* SV_Map */ void SV_Map_f(void){ if(Cmd_Argc() != 2){ Com_Printf("Usage: map \n"); return; } // start up the map SV_Map(Cmd_Argv(1)); } /* SV_GameMap_f */ void SV_GameMap_f(void){ if(Cmd_Argc() != 2){ Com_Printf("Usage: gamemap \n"); return; } // start up the map SV_Map(Cmd_Argv(1)); } /* SV_Kick_f Kick a user off of the server */ void SV_Kick_f(void){ if(!svs.initialized){ Com_Printf("No server running.\n"); return; } if(Cmd_Argc() != 2){ Com_Printf("Usage: kick \n"); return; } if(!SV_SetPlayer()) return; SV_KickClient(sv_client, NULL); } /* SV_Status_f */ void SV_Status_f(void){ int i, j, l; extern int zlib_accum, playerstate_accum; client_t *cl; char *s; int ping; if(!svs.clients){ Com_Printf("No server running.\n"); return; } Com_Printf("map: %s\n", sv.name); Com_Printf("protocol: %d\n", sv.protocol); Com_Printf("num score ping name lastmsg exts address qport \n"); Com_Printf("--- ----- ---- --------------- ------- ---- --------------------- ------\n"); for(i = 0, cl = svs.clients; i < maxclients->value; i++, cl++){ if(!cl->state) continue; Com_Printf("%3i ", 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 "); else { ping = cl->ping < 9999 ? cl->ping : 9999; Com_Printf("%4i ", ping); } Com_Printf("%s", cl->name); l = 16 - strlen(cl->name); for(j = 0; j < l; j++) Com_Printf(" "); Com_Printf("%7i ", svs.realtime - cl->lastmessage); Com_Printf("%d ", (int)cl->quetoo); s = NET_AdrToString(cl->netchan.remote_address); Com_Printf("%s", s); l = 22 - strlen(s); for(j = 0; j < l; j++) Com_Printf(" "); Com_Printf("%5i", cl->netchan.qport); Com_Printf("\n"); } Com_Printf("Zlib: %d bytes saved\n", zlib_accum); Com_Printf("Playerstate: %d bytes saved\n", playerstate_accum); Com_Printf("Total savings: %d bytes\n", zlib_accum + playerstate_accum); } /* SV_ConSay_f */ void SV_ConSay_f(void){ client_t *client; int j; char *p; char text[1024]; if(Cmd_Argc() < 2) return; strcpy(text, "console: "); p = Cmd_Args(); if(*p == '"'){ p++; p[strlen(p) - 1] = 0; } strcat(text, p); for(j = 0, client = svs.clients; j < maxclients->value; j++, client++){ if(client->state != cs_spawned) continue; SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text); } } /* SV_Heartbeat_f */ void SV_Heartbeat_f(void){ svs.last_heartbeat = -9999999; } /* SV_Serverinfo_f Examine or change the serverinfo string */ void SV_Serverinfo_f(void){ Com_Printf("Server info settings:\n"); Info_Print(Cvar_Serverinfo()); } /* SV_DumpUser_f Examine all a users info strings */ void SV_DumpUser_f(void){ if(Cmd_Argc() != 2){ Com_Printf("Usage: info \n"); return; } if(!SV_SetPlayer()) return; Com_Printf("userinfo\n"); Com_Printf("--------\n"); Info_Print(sv_client->userinfo); } /* SV_ServerCommand_f Let the game dll handle a command */ void SV_ServerCommand_f(void){ if(!ge){ Com_Printf("No game loaded.\n"); return; } ge->ServerCommand(); } /* SV_InitOperatorCommands */ void SV_InitOperatorCommands(void){ 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); Cmd_AddCommand("demo", SV_Demo_f); Cmd_AddCommand("map", SV_Map_f); Cmd_AddCommand("gamemap", SV_GameMap_f); Cmd_AddCommand("setmaster", SV_SetMaster_f); if(dedicated->value) Cmd_AddCommand("say", SV_ConSay_f); Cmd_AddCommand("sv", SV_ServerCommand_f); }