422 lines
10 KiB
C++
422 lines
10 KiB
C++
/**
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* 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 <http://www.sourcemod.net/license.php>.
|
|
*
|
|
* Version: $Id$
|
|
*/
|
|
|
|
#include "sm_srvcmds.h"
|
|
#include "sm_stringutil.h"
|
|
#include "CoreConfig.h"
|
|
#include "ConVarManager.h"
|
|
#include "logic_bridge.h"
|
|
#include <sourcemod_version.h>
|
|
|
|
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<ConsoleEntry *>::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<ConVar *>(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<ConsoleEntry *>::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<ConsoleEntry *>::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 <command> [arguments]");
|
|
|
|
List<ConsoleEntry *>::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 <file> or <log> 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();
|
|
}
|
|
|