3 * =============================================================================
5 * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_srvcmds.h"
33 #include <sourcemod_version.h>
34 #include "sm_stringutil.h"
35 #include "CoreConfig.h"
36 #include "ConVarManager.h"
37 #include "logic_bridge.h"
39 RootConsoleMenu g_RootMenu;
41 ConVar sourcemod_version("sourcemod_version", SM_VERSION_STRING, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");
43 RootConsoleMenu::RootConsoleMenu()
45 m_pCommands = sm_trie_create();
46 m_CfgExecDone = false;
49 RootConsoleMenu::~RootConsoleMenu()
51 sm_trie_destroy(m_pCommands);
53 List<ConsoleEntry *>::iterator iter;
54 for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
61 void RootConsoleMenu::OnSourceModStartup(bool late)
63 #if SOURCE_ENGINE >= SE_ORANGEBOX
66 CONVAR_REGISTER(this);
67 AddRootConsoleCommand("version", "Display version information", this);
68 AddRootConsoleCommand("credits", "Display credits listing", this);
71 void RootConsoleMenu::OnSourceModAllInitialized()
73 sharesys->AddInterface(NULL, this);
76 void RootConsoleMenu::OnSourceModShutdown()
78 RemoveRootConsoleCommand("credits", this);
79 RemoveRootConsoleCommand("version", this);
82 bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
84 META_REGCVAR(pCommand);
86 /* Override values of convars created by SourceMod convar manager if specified on command line */
87 const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName());
88 if (cmdLineValue && !pCommand->IsCommand())
90 static_cast<ConVar *>(pCommand)->SetValue(cmdLineValue);
96 void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
102 size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
105 if (len >= sizeof(buffer) - 1)
110 buffer[len++] = '\n';
114 META_CONPRINT(buffer);
117 bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
119 return _AddRootConsoleCommand(cmd, text, pHandler, false);
122 bool RootConsoleMenu::AddRootConsoleCommand2(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
124 return _AddRootConsoleCommand(cmd, text, pHandler, true);
127 bool RootConsoleMenu::_AddRootConsoleCommand(const char *cmd,
129 IRootConsoleCommand *pHandler,
132 if (sm_trie_retrieve(m_pCommands, cmd, NULL))
137 /* Sort this into the menu */
138 List<ConsoleEntry *>::iterator iter = m_Menu.begin();
139 ConsoleEntry *pEntry;
140 bool inserted = false;
141 while (iter != m_Menu.end())
144 if (strcmp(cmd, pEntry->command.c_str()) < 0)
146 ConsoleEntry *pNew = new ConsoleEntry;
147 pNew->command.assign(cmd);
148 pNew->description.assign(text);
149 pNew->version2 = version2;
150 pNew->cmd = pHandler;
151 sm_trie_insert(m_pCommands, cmd, pNew);
152 m_Menu.insert(iter, pNew);
161 ConsoleEntry *pNew = new ConsoleEntry;
162 pNew->command.assign(cmd);
163 pNew->description.assign(text);
164 pNew->version2 = version2;
165 pNew->cmd = pHandler;
166 sm_trie_insert(m_pCommands, cmd, pNew);
167 m_Menu.push_back(pNew);
173 bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
175 sm_trie_delete(m_pCommands, cmd);
177 List<ConsoleEntry *>::iterator iter;
178 ConsoleEntry *pEntry;
179 for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
182 if (pEntry->command.compare(cmd) == 0)
193 void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
196 size_t len, cmdlen = strlen(cmd);
198 len = UTIL_Format(buffer, sizeof(buffer), " %s", cmd);
201 size_t num = 16 - cmdlen;
202 for (size_t i = 0; i < num; i++)
206 len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
207 ConsolePrint("%s", buffer);
211 const char *RootConsoleMenu::GetInterfaceName()
213 return SMINTERFACE_ROOTCONSOLE_NAME;
216 unsigned int RootConsoleMenu::GetInterfaceVersion()
218 return SMINTERFACE_ROOTCONSOLE_VERSION;
221 #if SOURCE_ENGINE==SE_EPISODEONE || SOURCE_ENGINE==SE_DARKMESSIAH
222 class CCommandArgs : public ICommandArgs
225 CCommandArgs(const CCommand& _cmd)
228 const char *Arg(int n) const
230 return engine->Cmd_Argv(n);
234 return engine->Cmd_Argc();
236 const char *ArgS() const
238 return engine->Cmd_Args();
242 class CCommandArgs : public ICommandArgs
246 CCommandArgs(const CCommand& _cmd) : cmd(&_cmd)
249 const char *Arg(int n) const
257 const char *ArgS() const
264 void RootConsoleMenu::GotRootCmd(const CCommand &cmd)
266 unsigned int argnum = cmd.ArgC();
270 const char *cmdname = cmd.Arg(1);
271 if (strcmp(cmdname, "internal") == 0)
275 const char *arg = cmd.Arg(2);
276 if (strcmp(arg, "1") == 0)
278 SM_ConfigsExecuted_Global();
280 else if (strcmp(arg, "2") == 0)
284 SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3)));
291 CCommandArgs ocmd(cmd);
294 if (sm_trie_retrieve(m_pCommands, cmdname, (void **)&entry))
298 entry->cmd->OnRootConsoleCommand2(cmdname, &ocmd);
302 entry->cmd->OnRootConsoleCommand(cmdname, cmd);
308 ConsolePrint("SourceMod Menu:");
309 ConsolePrint("Usage: sm <command> [arguments]");
311 List<ConsoleEntry *>::iterator iter;
312 ConsoleEntry *pEntry;
313 for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
316 DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
320 void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
322 if (strcmp(cmdname, "credits") == 0)
324 ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
325 ConsolePrint(" Development would not have been possible without the following people:");
326 ConsolePrint(" David \"BAILOPAN\" Anderson");
327 ConsolePrint(" Matt \"pRED\" Woodrow");
328 ConsolePrint(" Scott \"DS\" Ehlert");
329 ConsolePrint(" Fyren");
330 ConsolePrint(" Nicholas \"psychonic\" Hastings");
331 ConsolePrint(" Asher \"asherkin\" Baker");
332 ConsolePrint(" Borja \"faluco\" Ferrer");
333 ConsolePrint(" Pavol \"PM OnoTo\" Marko");
334 ConsolePrint(" Special thanks to Liam, ferret, and Mani");
335 ConsolePrint(" Special thanks to Viper and SteamFriends");
336 ConsolePrint(" http://www.sourcemod.net/");
338 else if (strcmp(cmdname, "version") == 0)
340 ConsolePrint(" SourceMod Version Information:");
341 ConsolePrint(" SourceMod Version: %s", SM_VERSION_STRING);
342 ConsolePrint(" SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
343 ConsolePrint(" SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion());
344 ConsolePrint(" Compiled on: %s %s", __DATE__, __TIME__);
345 ConsolePrint(" Build ID: %s", SM_BUILD_UNIQUEID);
346 ConsolePrint(" http://www.sourcemod.net/");
350 CON_COMMAND(sm, "SourceMod Menu")
352 #if SOURCE_ENGINE <= SE_DARKMESSIAH
355 g_RootMenu.GotRootCmd(args);
358 FILE *g_pHndlLog = NULL;
360 void write_handles_to_log(const char *fmt, ...)
365 vfprintf(g_pHndlLog, fmt, ap);
366 fprintf(g_pHndlLog, "\n");
370 void write_handles_to_game(const char *fmt, ...)
377 len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap);
381 buffer[len+1] = '\0';
383 engine->LogPrint(buffer);
386 CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
388 #if SOURCE_ENGINE <= SE_DARKMESSIAH
393 g_RootMenu.ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
397 if (strcmp(args.Arg(1), "log") != 0)
399 const char *arg = args.Arg(1);
400 FILE *fp = fopen(arg, "wt");
403 g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
408 logicore.DumpHandles(write_handles_to_log);
415 logicore.DumpHandles(write_handles_to_game);