core/sm_srvcmds.cpp
author David Anderson <dvander@alliedmods.net>
Fri Feb 16 04:16:31 2007 +0000 (2007-02-16)
changeset 502 4530ea065a8b
parent 370 d3a484f98f6d
child 524 2a6bbf305c17
permissions -rw-r--r--
fixed a serious potential bug with swapping plugins to debug mode, leaving stale function pointers without plugin removal
     1 /**
     2  * ===============================================================
     3  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     4  * ===============================================================
     5  *
     6  * This file is not open source and may not be copied without explicit
     7  * written permission of AlliedModders LLC.  This file may not be redistributed 
     8  * in whole or significant part.
     9  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    10  *
    11  * Version: $Id$
    12  */
    13 
    14 #include "sm_srvcmds.h"
    15 #include "sm_version.h"
    16 #include "sm_stringutil.h"
    17 
    18 RootConsoleMenu g_RootMenu;
    19 
    20 RootConsoleMenu::RootConsoleMenu()
    21 {
    22 	m_pCommands = sm_trie_create();
    23 }
    24 
    25 RootConsoleMenu::~RootConsoleMenu()
    26 {
    27 	sm_trie_destroy(m_pCommands);
    28 
    29 	List<ConsoleEntry *>::iterator iter;
    30 	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
    31 	{
    32 		delete (*iter);
    33 	}
    34 	m_Menu.clear();
    35 }
    36 
    37 void RootConsoleMenu::OnSourceModStartup(bool late)
    38 {
    39 	ConCommandBaseMgr::OneTimeInit(this);
    40 	AddRootConsoleCommand("version", "Display version information", this);
    41 	AddRootConsoleCommand("credits", "Display credits listing", this);
    42 }
    43 
    44 void RootConsoleMenu::OnSourceModShutdown()
    45 {
    46 	RemoveRootConsoleCommand("credits", this);
    47 	RemoveRootConsoleCommand("version", this);
    48 }
    49 
    50 bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
    51 {
    52 	META_REGCVAR(pCommand);
    53 
    54 	return true;
    55 }
    56 
    57 void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
    58 {
    59 	char buffer[512];
    60 
    61 	va_list ap;
    62 	va_start(ap, fmt);
    63 	size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
    64 	va_end(ap);
    65 
    66 	if (len >= sizeof(buffer) - 1)
    67 	{
    68 		buffer[510] = '\n';
    69 		buffer[511] = '\0';
    70 	} else {
    71 		buffer[len++] = '\n';
    72 		buffer[len] = '\0';
    73 	}
    74 	
    75 	META_CONPRINT(buffer);
    76 }
    77 
    78 bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
    79 {
    80 	if (sm_trie_retrieve(m_pCommands, cmd, NULL))
    81 	{
    82 		return false;
    83 	}
    84 
    85 	sm_trie_insert(m_pCommands, cmd, pHandler);
    86 
    87 	/* Sort this into the menu */
    88 	List<ConsoleEntry *>::iterator iter = m_Menu.begin();
    89 	ConsoleEntry *pEntry;
    90 	bool inserted = false;
    91 	while (iter != m_Menu.end())
    92 	{
    93 		pEntry = (*iter);
    94 		if (strcmp(cmd, pEntry->command.c_str()) < 0)
    95 		{
    96 			ConsoleEntry *pNew = new ConsoleEntry;
    97 			pNew->command.assign(cmd);
    98 			pNew->description.assign(text);
    99 			m_Menu.insert(iter, pNew);
   100 			inserted = true;
   101 			break;
   102 		}
   103 		iter++;
   104 	}
   105 
   106 	if (!inserted)
   107 	{
   108 		ConsoleEntry *pNew = new ConsoleEntry;
   109 		pNew->command.assign(cmd);
   110 		pNew->description.assign(text);
   111 		m_Menu.push_back(pNew);
   112 	}
   113 
   114 	return true;
   115 }
   116 
   117 bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
   118 {
   119 	/* Sanity tests */
   120 	IRootConsoleCommand *object;
   121 	if (sm_trie_retrieve(m_pCommands, cmd, (void **)&object))
   122 	{
   123 		if (object != pHandler)
   124 		{
   125 			return false;
   126 		}
   127 	} else {
   128 		return false;
   129 	}
   130 
   131 	sm_trie_delete(m_pCommands, cmd);
   132 
   133 	List<ConsoleEntry *>::iterator iter;
   134 	ConsoleEntry *pEntry;
   135 	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
   136 	{
   137 		pEntry = (*iter);
   138 		if (pEntry->command.compare(cmd) == 0)
   139 		{
   140 			delete pEntry;
   141 			m_Menu.erase(iter);
   142 			break;
   143 		}
   144 	}
   145 
   146 	return true;
   147 }
   148 
   149 void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
   150 {
   151 	char buffer[255];
   152 	size_t len, cmdlen = strlen(cmd);
   153 
   154 	len = snprintf(buffer, sizeof(buffer), "    %s", cmd);
   155 	if (cmdlen < 16)
   156 	{
   157 		size_t num = 16 - cmdlen;
   158 		for (size_t i = 0; i < num; i++)
   159 		{
   160 			buffer[len++] = ' ';
   161 		}
   162 		len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
   163 		ConsolePrint("%s", buffer);
   164 	}
   165 }
   166 
   167 void RootConsoleMenu::GotRootCmd()
   168 {
   169 	unsigned int argnum = GetArgumentCount();
   170 
   171 	if (argnum >= 2)
   172 	{
   173 		const char *cmd = GetArgument(1);
   174 		IRootConsoleCommand *pHandler;
   175 		if (sm_trie_retrieve(m_pCommands, cmd, (void **)&pHandler))
   176 		{
   177 			pHandler->OnRootConsoleCommand(cmd, argnum);
   178 			return;
   179 		}
   180 	}
   181 
   182 	ConsolePrint("SourceMod Menu:");
   183 	ConsolePrint("Usage: sm <command> [arguments]");
   184 
   185 	List<ConsoleEntry *>::iterator iter;
   186 	ConsoleEntry *pEntry;
   187 	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
   188 	{
   189 		pEntry = (*iter);
   190 		DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
   191 	}
   192 }
   193 
   194 const char *RootConsoleMenu::GetArgument(unsigned int argno)
   195 {
   196 	return engine->Cmd_Argv(argno);
   197 }
   198 
   199 const char *RootConsoleMenu::GetArguments()
   200 {
   201 	return engine->Cmd_Args();
   202 }
   203 
   204 unsigned int RootConsoleMenu::GetArgumentCount()
   205 {
   206 	return engine->Cmd_Argc();
   207 }
   208 
   209 void RootConsoleMenu::OnRootConsoleCommand(const char *cmd, unsigned int argcount)
   210 {
   211 	if (strcmp(cmd, "credits") == 0)
   212 	{
   213 		ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
   214 		ConsolePrint(" Development would not have been possible without the following people:");
   215 		ConsolePrint("  David \"BAILOPAN\" Anderson, lead developer");
   216 		ConsolePrint("  Borja \"faluco\" Ferrer, Core developer");
   217 		ConsolePrint("  Scott \"Damaged Soul\" Ehlert, SourceMM developer");
   218 		ConsolePrint("  Pavol \"PM OnoTo\" Marko, SourceHook developer");
   219 		ConsolePrint(" Special thanks to Viper of GameConnect");
   220 		ConsolePrint(" Special thanks to Mani of Mani-Admin-Plugin");
   221 		ConsolePrint(" http://www.sourcemod.net/");
   222 	} else if (strcmp(cmd, "version") == 0) {
   223 		ConsolePrint(" SourceMod Version Information:");
   224 		ConsolePrint("    SourceMod Version: %s", SOURCEMOD_VERSION);
   225 		ConsolePrint("    JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
   226 		ConsolePrint("    JIT Settings: %s", g_pVM->GetCPUOptimizations());
   227 		ConsolePrint("    http://www.sourcemod.net/");
   228 	}
   229 }
   230 
   231 CON_COMMAND(sm, "SourceMod Menu")
   232 {
   233 	g_RootMenu.GotRootCmd();
   234 }