/** * vim: set ts=4 sw=4 tw=99 noet : * ============================================================================= * SourceMod * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. * * 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, see . * * As a special exception, AlliedModders LLC gives you permission to link the * code of this program (as well as its derivative works) to "Half-Life 2," the * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software * by the Valve Corporation. You must obey the GNU General Public License in * all respects for all other code used. Additionally, AlliedModders LLC grants * this exception to all derivative works. AlliedModders LLC defines further * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * * Version: $Id$ */ #include "sm_srvcmds.h" #include "sm_stringutil.h" #include "CoreConfig.h" #include "ConVarManager.h" #include "logic_bridge.h" #include RootConsoleMenu g_RootMenu; ConVar sourcemod_version("sourcemod_version", SOURCEMOD_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version"); RootConsoleMenu::RootConsoleMenu() { m_CfgExecDone = false; } RootConsoleMenu::~RootConsoleMenu() { List::iterator iter; for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { delete (*iter); } m_Menu.clear(); } void RootConsoleMenu::OnSourceModStartup(bool late) { #if SOURCE_ENGINE >= SE_ORANGEBOX g_pCVar = icvar; #endif CONVAR_REGISTER(this); AddRootConsoleCommand("version", "Display version information", this); AddRootConsoleCommand("credits", "Display credits listing", this); } void RootConsoleMenu::OnSourceModAllInitialized() { sharesys->AddInterface(NULL, this); } void RootConsoleMenu::OnSourceModShutdown() { RemoveRootConsoleCommand("credits", this); RemoveRootConsoleCommand("version", this); } bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand) { META_REGCVAR(pCommand); /* Override values of convars created by SourceMod convar manager if specified on command line */ const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName()); if (cmdLineValue && !pCommand->IsCommand()) { static_cast(pCommand)->SetValue(cmdLineValue); } return true; } void RootConsoleMenu::ConsolePrint(const char *fmt, ...) { char buffer[512]; va_list ap; va_start(ap, fmt); size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); if (len >= sizeof(buffer) - 1) { buffer[510] = '\n'; buffer[511] = '\0'; } else { buffer[len++] = '\n'; buffer[len] = '\0'; } META_CONPRINT(buffer); } bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler) { return _AddRootConsoleCommand(cmd, text, pHandler, false); } bool RootConsoleMenu::AddRootConsoleCommand2(const char *cmd, const char *text, IRootConsoleCommand *pHandler) { return _AddRootConsoleCommand(cmd, text, pHandler, true); } bool RootConsoleMenu::_AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler, bool version2) { if (m_Commands.contains(cmd)) return false; /* Sort this into the menu */ List::iterator iter = m_Menu.begin(); ConsoleEntry *pEntry; bool inserted = false; while (iter != m_Menu.end()) { pEntry = (*iter); if (strcmp(cmd, pEntry->command.c_str()) < 0) { ConsoleEntry *pNew = new ConsoleEntry; pNew->command.assign(cmd); pNew->description.assign(text); pNew->version2 = version2; pNew->cmd = pHandler; m_Commands.insert(cmd, pNew); m_Menu.insert(iter, pNew); inserted = true; break; } iter++; } if (!inserted) { ConsoleEntry *pNew = new ConsoleEntry; pNew->command.assign(cmd); pNew->description.assign(text); pNew->version2 = version2; pNew->cmd = pHandler; m_Commands.insert(cmd, pNew); m_Menu.push_back(pNew); } return true; } bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler) { m_Commands.remove(cmd); List::iterator iter; ConsoleEntry *pEntry; for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { pEntry = (*iter); if (pEntry->command.compare(cmd) == 0) { delete pEntry; m_Menu.erase(iter); break; } } return true; } void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text) { char buffer[255]; size_t len, cmdlen = strlen(cmd); len = UTIL_Format(buffer, sizeof(buffer), " %s", cmd); if (cmdlen < 16) { size_t num = 16 - cmdlen; for (size_t i = 0; i < num; i++) { buffer[len++] = ' '; } len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text); ConsolePrint("%s", buffer); } } const char *RootConsoleMenu::GetInterfaceName() { return SMINTERFACE_ROOTCONSOLE_NAME; } unsigned int RootConsoleMenu::GetInterfaceVersion() { return SMINTERFACE_ROOTCONSOLE_VERSION; } #if SOURCE_ENGINE==SE_EPISODEONE || SOURCE_ENGINE==SE_DARKMESSIAH class CCommandArgs : public ICommandArgs { public: CCommandArgs(const CCommand& _cmd) { } const char *Arg(int n) const { return engine->Cmd_Argv(n); } int ArgC() const { return engine->Cmd_Argc(); } const char *ArgS() const { return engine->Cmd_Args(); } }; #else class CCommandArgs : public ICommandArgs { const CCommand *cmd; public: CCommandArgs(const CCommand& _cmd) : cmd(&_cmd) { } const char *Arg(int n) const { return cmd->Arg(n); } int ArgC() const { return cmd->ArgC(); } const char *ArgS() const { return cmd->ArgS(); } }; #endif void RootConsoleMenu::GotRootCmd(const CCommand &cmd) { unsigned int argnum = cmd.ArgC(); if (argnum >= 2) { const char *cmdname = cmd.Arg(1); if (strcmp(cmdname, "internal") == 0) { if (argnum >= 3) { const char *arg = cmd.Arg(2); if (strcmp(arg, "1") == 0) { SM_ConfigsExecuted_Global(); } else if (strcmp(arg, "2") == 0) { if (argnum >= 4) { SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3))); } } } return; } CCommandArgs ocmd(cmd); ConsoleEntry *entry; if (m_Commands.retrieve(cmdname, &entry)) { if (entry->version2) { entry->cmd->OnRootConsoleCommand2(cmdname, &ocmd); } else { entry->cmd->OnRootConsoleCommand(cmdname, cmd); } return; } } ConsolePrint("SourceMod Menu:"); ConsolePrint("Usage: sm [arguments]"); List::iterator iter; ConsoleEntry *pEntry; for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { pEntry = (*iter); DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str()); } } void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command) { if (strcmp(cmdname, "credits") == 0) { ConsolePrint(" SourceMod was developed by AlliedModders, LLC."); ConsolePrint(" Development would not have been possible without the following people:"); ConsolePrint(" David \"BAILOPAN\" Anderson"); ConsolePrint(" Matt \"pRED\" Woodrow"); ConsolePrint(" Scott \"DS\" Ehlert"); ConsolePrint(" Fyren"); ConsolePrint(" Nicholas \"psychonic\" Hastings"); ConsolePrint(" Asher \"asherkin\" Baker"); ConsolePrint(" Borja \"faluco\" Ferrer"); ConsolePrint(" Pavol \"PM OnoTo\" Marko"); ConsolePrint(" Special thanks to Liam, ferret, and Mani"); ConsolePrint(" Special thanks to Viper and SteamFriends"); ConsolePrint(" http://www.sourcemod.net/"); } else if (strcmp(cmdname, "version") == 0) { ConsolePrint(" SourceMod Version Information:"); ConsolePrint(" SourceMod Version: %s", SOURCEMOD_VERSION); if (g_pSourcePawn2->IsJitEnabled()) ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString()); else ConsolePrint(" SourcePawn Engine: %s (build %s NO JIT)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString()); ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion()); ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__); ConsolePrint(" Build ID: %s", SOURCEMOD_BUILD_ID); ConsolePrint(" http://www.sourcemod.net/"); } } CON_COMMAND(sm, "SourceMod Menu") { #if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif g_RootMenu.GotRootCmd(args); } FILE *g_pHndlLog = NULL; void write_handles_to_log(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(g_pHndlLog, fmt, ap); fprintf(g_pHndlLog, "\n"); va_end(ap); } void write_handles_to_game(const char *fmt, ...) { size_t len; va_list ap; char buffer[1024]; va_start(ap, fmt); len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap); va_end(ap); buffer[len] = '\n'; buffer[len+1] = '\0'; engine->LogPrint(buffer); } CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks") { #if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; #endif if (args.ArgC() < 2) { g_RootMenu.ConsolePrint("Usage: sm_dump_handles or for game logs"); return; } if (strcmp(args.Arg(1), "log") != 0) { const char *arg = args.Arg(1); FILE *fp = fopen(arg, "wt"); if (!fp) { g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg); return; } g_pHndlLog = fp; logicore.DumpHandles(write_handles_to_log); g_pHndlLog = NULL; fclose(fp); } else { logicore.DumpHandles(write_handles_to_game); } } CON_COMMAND(sm_reload_translations, "Reparses all loaded translation files") { translator->RebuildLanguageDatabase(); }