dvander@370: /**
ds@653: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
dvander@1231: * Copyright (C) 2004-2007 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"
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:
ds@627: extern void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue);
ds@627:
dvander@308: void RootConsoleMenu::OnSourceModStartup(bool late)
dvander@308: {
dvander@308: ConCommandBaseMgr::OneTimeInit(this);
dvander@308: AddRootConsoleCommand("version", "Display version information", this);
dvander@308: AddRootConsoleCommand("credits", "Display credits listing", this);
ds@627:
ds@627: ConVar *pHost = icvar->FindVar("hostname");
ds@627: pHost->InstallChangeCallback(_IntExt_OnHostnameChanged);
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@614: extern void _IntExt_EnableYams();
dvander@614:
dvander@308: void RootConsoleMenu::GotRootCmd()
dvander@308: {
dvander@308: unsigned int argnum = GetArgumentCount();
faluco@216:
faluco@216: if (argnum >= 2)
faluco@216: {
dvander@308: const char *cmd = GetArgument(1);
dvander@614: if (strcmp(cmd, "text") == 0)
dvander@614: {
dvander@614: _IntExt_EnableYams();
dvander@614: return;
dvander@978: } else if (strcmp(cmd, "internal") == 0) {
dvander@978: if (argnum >= 3)
dvander@978: {
dvander@978: const char *arg = GetArgument(2);
dvander@978: if (strcmp(arg, "1") == 0)
dvander@978: {
dvander@978: SM_ConfigsExecuted_Global();
dvander@978: } else if (strcmp(arg, "2") == 0) {
dvander@978: if (argnum >= 4)
dvander@978: {
dvander@978: SM_ConfigsExecuted_Plugin(atoi(GetArgument(3)));
dvander@978: }
dvander@978: }
dvander@978: }
dvander@978: return;
dvander@614: }
dvander@978:
dvander@308: IRootConsoleCommand *pHandler;
dvander@308: if (sm_trie_retrieve(m_pCommands, cmd, (void **)&pHandler))
faluco@216: {
dvander@308: pHandler->OnRootConsoleCommand(cmd, argnum);
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:
dvander@308: const char *RootConsoleMenu::GetArgument(unsigned int argno)
dvander@308: {
dvander@308: return engine->Cmd_Argv(argno);
dvander@308: }
dvander@308:
dvander@308: const char *RootConsoleMenu::GetArguments()
dvander@308: {
dvander@308: return engine->Cmd_Args();
dvander@282: }
dvander@308:
dvander@308: unsigned int RootConsoleMenu::GetArgumentCount()
dvander@308: {
dvander@308: return engine->Cmd_Argc();
dvander@308: }
dvander@308:
dvander@308: void RootConsoleMenu::OnRootConsoleCommand(const char *cmd, unsigned int argcount)
dvander@308: {
dvander@308: if (strcmp(cmd, "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@308: ConsolePrint(" Borja \"faluco\" Ferrer, Core developer");
ds@626: ConsolePrint(" Scott \"Damaged Soul\" Ehlert, Core 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@308: } else if (strcmp(cmd, "version") == 0) {
dvander@308: ConsolePrint(" SourceMod Version Information:");
dvander@566: ConsolePrint(" SourceMod Version: %s", SVN_FULL_VERSION);
dvander@308: ConsolePrint(" JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
dvander@308: ConsolePrint(" JIT Settings: %s", g_pVM->GetCPUOptimizations());
dvander@308: ConsolePrint(" http://www.sourcemod.net/");
dvander@308: }
dvander@308: }
dvander@308:
dvander@308: CON_COMMAND(sm, "SourceMod Menu")
dvander@308: {
dvander@308: g_RootMenu.GotRootCmd();
dvander@308: }
dvander@900:
dvander@900: CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
dvander@900: {
dvander@900: if (engine->Cmd_Argc() < 2)
dvander@900: {
dvander@900: g_RootMenu.ConsolePrint("Usage: sm_dump_handles ");
dvander@900: return;
dvander@900: }
dvander@900:
dvander@900: const char *arg = engine->Cmd_Argv(1);
dvander@900: FILE *fp = fopen(arg, "wt");
dvander@900: if (!fp)
dvander@900: {
dvander@900: g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
dvander@900: return;
dvander@900: }
dvander@900:
dvander@900: g_HandleSys.Dump(fp);
dvander@900:
dvander@900: fclose(fp);
dvander@900: }