dvander@370: /** ds@653: * vim: set ts=4 : ds@1330: * ============================================================================= dvander@1231: * SourceMod ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. ds@1330: * ============================================================================= dvander@370: * ds@1330: * This program is free software; you can redistribute it and/or modify it under ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the ds@1330: * Free Software Foundation. dvander@1231: * ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ds@1330: * details. dvander@1231: * ds@1330: * You should have received a copy of the GNU General Public License along with ds@1330: * this program. If not, see . dvander@1231: * ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants ds@1330: * this exception to all derivative works. AlliedModders LLC defines further ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), ds@1330: * or . dvander@370: * dvander@370: * Version: $Id$ dvander@370: */ dvander@370: faluco@216: #include "sm_srvcmds.h" faluco@270: #include "sm_version.h" faluco@274: #include "sm_stringutil.h" dvander@900: #include "HandleSys.h" dvander@978: #include "CoreConfig.h" dvander@1770: #include "ConVarManager.h" dvander@1883: #include "ShareSys.h" faluco@216: dvander@308: RootConsoleMenu g_RootMenu; faluco@216: dvander@566: ConVar sourcemod_version("sourcemod_version", SVN_FULL_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version"); dvander@524: dvander@308: RootConsoleMenu::RootConsoleMenu() faluco@216: { dvander@308: m_pCommands = sm_trie_create(); dvander@978: m_CfgExecDone = false; faluco@216: } faluco@216: dvander@308: RootConsoleMenu::~RootConsoleMenu() dvander@308: { dvander@308: sm_trie_destroy(m_pCommands); dvander@308: dvander@308: List::iterator iter; dvander@308: for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) dvander@308: { dvander@308: delete (*iter); dvander@308: } dvander@308: m_Menu.clear(); dvander@308: } dvander@308: dvander@308: void RootConsoleMenu::OnSourceModStartup(bool late) dvander@308: { faluco@1541: #if defined ORANGEBOX_BUILD dvander@1542: g_pCVar = icvar; faluco@1541: #endif faluco@1541: CONVAR_REGISTER(this); dvander@308: AddRootConsoleCommand("version", "Display version information", this); dvander@308: AddRootConsoleCommand("credits", "Display credits listing", this); dvander@1770: } ds@627: dvander@1770: void RootConsoleMenu::OnSourceModAllInitialized() dvander@1770: { dvander@1883: g_ShareSys.AddInterface(NULL, this); dvander@308: } dvander@308: dvander@308: void RootConsoleMenu::OnSourceModShutdown() dvander@308: { dvander@308: RemoveRootConsoleCommand("credits", this); dvander@308: RemoveRootConsoleCommand("version", this); dvander@308: } dvander@308: dvander@308: bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand) faluco@216: { faluco@216: META_REGCVAR(pCommand); faluco@216: ds@657: /* Override values of convars created by SourceMod convar manager if specified on command line */ ds@657: const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName()); ds@657: if (cmdLineValue && !pCommand->IsCommand()) ds@657: { ds@657: static_cast(pCommand)->SetValue(cmdLineValue); ds@657: } ds@657: faluco@216: return true; faluco@216: } faluco@216: dvander@308: void RootConsoleMenu::ConsolePrint(const char *fmt, ...) dvander@308: { dvander@308: char buffer[512]; dvander@308: dvander@308: va_list ap; dvander@308: va_start(ap, fmt); dvander@308: size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap); dvander@308: va_end(ap); dvander@308: dvander@324: if (len >= sizeof(buffer) - 1) dvander@308: { dvander@308: buffer[510] = '\n'; dvander@308: buffer[511] = '\0'; dvander@308: } else { dvander@308: buffer[len++] = '\n'; dvander@308: buffer[len] = '\0'; dvander@308: } dvander@308: dvander@308: META_CONPRINT(buffer); dvander@308: } dvander@308: dvander@308: bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler) faluco@216: { dvander@308: if (sm_trie_retrieve(m_pCommands, cmd, NULL)) dvander@308: { dvander@308: return false; dvander@308: } dvander@308: dvander@308: sm_trie_insert(m_pCommands, cmd, pHandler); dvander@308: dvander@308: /* Sort this into the menu */ dvander@308: List::iterator iter = m_Menu.begin(); dvander@308: ConsoleEntry *pEntry; dvander@308: bool inserted = false; dvander@308: while (iter != m_Menu.end()) dvander@308: { dvander@308: pEntry = (*iter); dvander@308: if (strcmp(cmd, pEntry->command.c_str()) < 0) dvander@308: { dvander@308: ConsoleEntry *pNew = new ConsoleEntry; dvander@308: pNew->command.assign(cmd); dvander@308: pNew->description.assign(text); dvander@308: m_Menu.insert(iter, pNew); dvander@308: inserted = true; dvander@308: break; dvander@308: } dvander@308: iter++; dvander@308: } dvander@308: dvander@308: if (!inserted) dvander@308: { dvander@308: ConsoleEntry *pNew = new ConsoleEntry; dvander@308: pNew->command.assign(cmd); dvander@308: pNew->description.assign(text); dvander@308: m_Menu.push_back(pNew); dvander@308: } dvander@308: dvander@308: return true; dvander@308: } dvander@308: dvander@308: bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler) dvander@308: { dvander@308: /* Sanity tests */ dvander@308: IRootConsoleCommand *object; dvander@308: if (sm_trie_retrieve(m_pCommands, cmd, (void **)&object)) dvander@308: { dvander@308: if (object != pHandler) dvander@308: { dvander@308: return false; dvander@308: } dvander@308: } else { dvander@308: return false; dvander@308: } dvander@308: dvander@308: sm_trie_delete(m_pCommands, cmd); dvander@308: dvander@308: List::iterator iter; dvander@308: ConsoleEntry *pEntry; dvander@308: for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) dvander@308: { dvander@308: pEntry = (*iter); dvander@308: if (pEntry->command.compare(cmd) == 0) dvander@308: { dvander@308: delete pEntry; dvander@308: m_Menu.erase(iter); dvander@308: break; dvander@308: } dvander@308: } dvander@308: dvander@308: return true; dvander@308: } dvander@308: dvander@309: void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text) dvander@309: { dvander@309: char buffer[255]; dvander@309: size_t len, cmdlen = strlen(cmd); dvander@309: faluco@651: len = UTIL_Format(buffer, sizeof(buffer), " %s", cmd); dvander@309: if (cmdlen < 16) dvander@309: { dvander@309: size_t num = 16 - cmdlen; dvander@309: for (size_t i = 0; i < num; i++) dvander@309: { dvander@309: buffer[len++] = ' '; dvander@309: } dvander@309: len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text); dvander@309: ConsolePrint("%s", buffer); dvander@309: } dvander@309: } dvander@309: dvander@1883: const char *RootConsoleMenu::GetInterfaceName() dvander@1883: { dvander@1883: return SMINTERFACE_ROOTCONSOLE_NAME; dvander@1883: } dvander@1883: dvander@1883: unsigned int RootConsoleMenu::GetInterfaceVersion() dvander@1883: { dvander@1883: return SMINTERFACE_ROOTCONSOLE_VERSION; dvander@1883: } dvander@1883: faluco@1541: void RootConsoleMenu::GotRootCmd(const CCommand &cmd) dvander@308: { faluco@1541: unsigned int argnum = cmd.ArgC(); faluco@216: faluco@216: if (argnum >= 2) faluco@216: { faluco@1541: const char *cmdname = cmd.Arg(1); dvander@1902: if (strcmp(cmdname, "internal") == 0) dvander@1630: { dvander@978: if (argnum >= 3) dvander@978: { faluco@1541: const char *arg = cmd.Arg(2); dvander@978: if (strcmp(arg, "1") == 0) dvander@978: { dvander@978: SM_ConfigsExecuted_Global(); dvander@1630: } dvander@1630: else if (strcmp(arg, "2") == 0) dvander@1630: { dvander@978: if (argnum >= 4) dvander@978: { faluco@1541: SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3))); dvander@978: } dvander@978: } dvander@978: } dvander@978: return; dvander@614: } dvander@978: dvander@308: IRootConsoleCommand *pHandler; faluco@1541: if (sm_trie_retrieve(m_pCommands, cmdname, (void **)&pHandler)) faluco@216: { faluco@1541: pHandler->OnRootConsoleCommand(cmdname, cmd); faluco@270: return; faluco@216: } faluco@216: } dvander@308: dvander@308: ConsolePrint("SourceMod Menu:"); dvander@308: ConsolePrint("Usage: sm [arguments]"); dvander@308: dvander@308: List::iterator iter; dvander@308: ConsoleEntry *pEntry; dvander@308: for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) dvander@308: { dvander@308: pEntry = (*iter); dvander@309: DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str()); dvander@308: } dvander@308: } dvander@308: faluco@1541: void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command) dvander@308: { faluco@1541: if (strcmp(cmdname, "credits") == 0) dvander@308: { dvander@308: ConsolePrint(" SourceMod was developed by AlliedModders, LLC."); dvander@308: ConsolePrint(" Development would not have been possible without the following people:"); dvander@308: ConsolePrint(" David \"BAILOPAN\" Anderson, lead developer"); dvander@2105: ConsolePrint(" Borja \"faluco\" Ferrer, core developer"); dvander@2105: ConsolePrint(" Scott \"Damaged Soul\" Ehlert, core developer"); dvander@2105: ConsolePrint(" Matt \"pRED\" Woodrow, core developer"); dvander@2105: ConsolePrint(" Michael \"ferret\" McKoy, plugin developer"); dvander@308: ConsolePrint(" Pavol \"PM OnoTo\" Marko, SourceHook developer"); dvander@308: ConsolePrint(" Special thanks to Viper of GameConnect"); dvander@308: ConsolePrint(" Special thanks to Mani of Mani-Admin-Plugin"); dvander@308: ConsolePrint(" http://www.sourcemod.net/"); dvander@2105: } dvander@2105: else if (strcmp(cmdname, "version") == 0) dvander@2105: { dvander@308: ConsolePrint(" SourceMod Version Information:"); dvander@566: ConsolePrint(" SourceMod Version: %s", SVN_FULL_VERSION); dvander@2193: ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString()); dvander@2193: ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion()); dvander@2105: ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__); dvander@2281: ConsolePrint(" Build ID: %s", SM_BUILD_UNIQUEID); dvander@308: ConsolePrint(" http://www.sourcemod.net/"); dvander@308: } dvander@308: } dvander@308: dvander@308: CON_COMMAND(sm, "SourceMod Menu") dvander@308: { faluco@1541: #if !defined ORANGEBOX_BUILD faluco@1541: CCommand args; faluco@1541: #endif faluco@1541: g_RootMenu.GotRootCmd(args); dvander@308: } dvander@900: dvander@1687: FILE *g_pHndlLog = NULL; dvander@1687: dvander@1687: void write_handles_to_log(const char *fmt, ...) dvander@1687: { dvander@1687: va_list ap; dvander@1687: dvander@1687: va_start(ap, fmt); dvander@1687: vfprintf(g_pHndlLog, fmt, ap); dvander@1687: fprintf(g_pHndlLog, "\n"); dvander@1687: va_end(ap); dvander@1687: } dvander@1687: dvander@1687: void write_handles_to_game(const char *fmt, ...) dvander@1687: { dvander@1687: size_t len; dvander@1687: va_list ap; dvander@1687: char buffer[1024]; dvander@1687: dvander@1687: va_start(ap, fmt); dvander@1687: len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap); dvander@1687: va_end(ap); dvander@1687: dvander@1687: buffer[len] = '\n'; dvander@1687: buffer[len+1] = '\0'; dvander@1687: dvander@1687: engine->LogPrint(buffer); dvander@1687: } dvander@1687: dvander@900: CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks") dvander@900: { faluco@1541: #if !defined ORANGEBOX_BUILD faluco@1541: CCommand args; faluco@1541: #endif faluco@1541: if (args.ArgC() < 2) dvander@900: { dvander@1687: g_RootMenu.ConsolePrint("Usage: sm_dump_handles or for game logs"); dvander@900: return; dvander@900: } dvander@900: dvander@1687: if (strcmp(args.Arg(1), "log") != 0) dvander@900: { dvander@1687: const char *arg = args.Arg(1); dvander@1687: FILE *fp = fopen(arg, "wt"); dvander@1687: if (!fp) dvander@1687: { dvander@1687: g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg); dvander@1687: return; dvander@1687: } dvander@900: dvander@1687: g_pHndlLog = fp; dvander@1687: g_HandleSys.Dump(write_handles_to_log); dvander@1687: g_pHndlLog = NULL; dvander@900: dvander@1687: fclose(fp); dvander@1687: } dvander@1687: else dvander@1687: { dvander@1687: g_HandleSys.Dump(write_handles_to_game); dvander@1687: } dvander@900: }