/* Relay -- a tool to record and play Quake2 demos Copyright (C) 2000 Conor Davis 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. Conor Davis cedavis@planetquake.com */ #include #include "sv_local.h" qboolean svcmd_alias(); qboolean svcmd_cmdlist(); qboolean svcmd_cvarlist(); qboolean svcmd_echo(); qboolean svcmd_kick(); qboolean svcmd_killserver(); qboolean svcmd_map(); qboolean svcmd_quit(); qboolean svcmd_set(); qboolean svcmd_status(); qboolean svcmd_wait(); qboolean svcmd_waitfor(); typedef struct alias_s { char *name; char *value; struct alias_s *next; } alias_t; static struct { char *name; qboolean (*func)(); } cmdlist[] = { {"alias", svcmd_alias}, {"cmdlist", svcmd_cmdlist}, {"cvarlist", svcmd_cvarlist}, {"echo", svcmd_echo}, {"kick", svcmd_kick}, {"killserver", svcmd_killserver}, {"map", svcmd_map}, {"quit", svcmd_quit}, {"set", svcmd_set}, {"status", svcmd_status}, {"wait", svcmd_wait}, {"waitfor", svcmd_waitfor}, {NULL, NULL} }; static alias_t *alias_head = NULL; void FreeAllAliases() { alias_t *alias, *next; for (alias = alias_head; alias; alias = next) { next = alias->next; Z_Free(alias->name); Z_Free(alias->value); Z_Free(alias); } alias_head = NULL; } qboolean svcmd_alias() { alias_t *alias; char temp[1024]; int i; if (Cmd_Argc() < 2) { printf("Current alias commands:\n"); for (alias = alias_head; alias; alias = alias->next) printf("%s : %s\n", alias->name, alias->value); return true; } temp[0] = 0; for (i = 2; i < Cmd_Argc(); i++) { strcat(temp, Cmd_Argv(i)); if (i != Cmd_Argc() - 1) strcat(temp, " "); } strcat(temp, "\n"); for (alias = alias_head; alias; alias = alias->next) { if (!strcmp(alias->name, Cmd_Argv(1))) { Z_Free(alias->value); break; } } if (!alias) { alias = Z_Malloc(sizeof(alias_t)); alias->name = Z_Strdup(Cmd_Argv(1)); alias->next = alias_head; alias_head = alias; } alias->value = Z_Strdup(temp); return true; } qboolean svcmd_cmdlist() { int i; for (i = 0; cmdlist[i].name; i++) printf("%s\n", cmdlist[i].name); printf("%d commands\n", i); return true; } qboolean svcmd_cvarlist() { cvar_t *var; int i; for (var = server.cvars, i = 0; var; var = var->next, i++) { printf("%c%c%c%c %s \"%s\"\n", (var->flags & CVAR_ARCHIVE ? '*' : ' '), (var->flags & CVAR_USERINFO ? 'U' : ' '), (var->flags & CVAR_SERVERINFO ? 'S' : ' '), (var->flags & CVAR_NOSET ? '-' : (var->flags & CVAR_LATCH ? 'L' : ' ')), var->name, var->string); } printf("%d cvars\n", i); return true; } qboolean svcmd_echo() { int i; for (i = 1; i < Cmd_Argc(); i++) printf("%s ", Cmd_Argv(i)); printf("\n"); return true; } qboolean svcmd_kick() { int i, id = 0; client_t *client; if (Cmd_Argc() != 2) { printf("usage: kick \n"); return true; } if (isdigit(Cmd_Argv(1)[0])) { id = atoi(Cmd_Argv(1)); if (id >= server.maxclients || server.clients[id].status == CL_UNCONNECTED) { printf("%s is not a valid userid\n", Cmd_Argv(1)); return true; } printf("%s was kicked\n", server.clients[id].netname); DropClient(&server.clients[id], "You were kicked\n"); return true; } for (i = 0, client = server.clients; i < server.maxclients; i++, client++) { if (client->status == CL_UNCONNECTED) continue; if (!strcmp(Cmd_Argv(1), client->netname)) { printf("%s was kicked\n", client->netname); DropClient(&server.clients[id], "You were kicked\n"); return true; } } printf("%s is not a valid userid\n", Cmd_Argv(1)); return true; } qboolean svcmd_killserver() { KillServer("Server was killed\n"); return true; } qboolean svcmd_map() { if (Cmd_Argc() < 2) { printf("Usage: map [.rla]\n"); return true; } SpawnServer(Cmd_Argv(1)); return true; } qboolean svcmd_quit() { CloseProgram(0); return true; } qboolean svcmd_set() { int flags; cvar_t *var; flags = 0; if (Cmd_Argc() < 3 || Cmd_Argc() > 4) { printf("Usage: set [u / s]\n"); return true; } if (Cmd_Argc() == 4) { switch(Cmd_Argv(3)[0]) { case 'u': flags = CVAR_USERINFO; break; case 's': flags = CVAR_SERVERINFO; break; default: printf("flags can only be 'u' or 's'\n"); break; } } var = cvar(Cmd_Argv(1), Cmd_Argv(2), 0); cvar_set(Cmd_Argv(1), Cmd_Argv(2)); if (var->flags & CVAR_NOSET) return true; if (flags & CVAR_USERINFO) var->flags = (var->flags | CVAR_USERINFO) & ~CVAR_SERVERINFO; else if (flags & CVAR_SERVERINFO) var->flags = (var->flags | CVAR_SERVERINFO) & ~CVAR_USERINFO; return true; } qboolean svcmd_status() { int i; client_t *client; if (server.status == SV_IDLE) { printf("No server running.\n"); return true; } printf("demo: %s\n", cvar_demoname->string); printf("map: %s\n", cvar_mapname->string); printf("num ping name address qport\n"); printf("--- ---- --------------- --------------------- ------\n"); for (i = 0, client = server.clients; i < server.maxclients; i++, client++) { if (client->status == CL_UNCONNECTED) continue; printf("%3d %4d %-15s %-21s %5d\n", i, 0, client->netname, UDP_AddrToString(&client->net.addr), client->net.qport); } return true; } qboolean svcmd_wait() { return false; } qboolean svcmd_waitfor() { if (Cmd_Argc() < 2) { printf("Usage: waitfor \n"); return true; } server.nextcommand_time = mstime() + atol(Cmd_Argv(1)); return false; } qboolean RunConsoleCommand() { int i; const char *cmd; alias_t *alias; cvar_t *var; if (Cmd_Argc() == 0) return true; cmd = Cmd_Argv(0); // search commands for (i = 0; cmdlist[i].name; i++) { if (!strcmp(cmd, cmdlist[i].name)) return cmdlist[i].func(); } // search aliases for (alias = alias_head; alias; alias = alias->next) { if (!strcmp(cmd, alias->name)) { Cmd_InsertText(&server.console_commandstring, alias->value); return true; } } // serch cvars for (var = server.cvars; var; var = var->next) { if (!strcmp(cmd, var->name)) { if (Cmd_Argc() < 2) printf("\"%s\" is \"%s\"\n", var->name, var->string); else cvar_set(var->name, Cmd_Argv(1)); return true; } } printf("Unknown command \"%s\"\n", cmd); return true; }