core/sm_srvcmds.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jun 02 05:03:27 2008 +0000 (2008-06-02)
changeset 2105 ad190b9bb5af
parent 1952 b7aa2b626807
child 2193 db7c6362f3f2
permissions -rw-r--r--
phase0, new versioning. we don't use build numbers anymore except (VS_VERSIONINFO stays until phase 3 is done)
ds@1952
     1
/**
ds@1952
     2
 * vim: set ts=4 :
ds@1952
     3
 * =============================================================================
ds@1952
     4
 * SourceMod
ds@1952
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1952
     6
 * =============================================================================
ds@1952
     7
 *
ds@1952
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1952
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1952
    10
 * Free Software Foundation.
ds@1952
    11
 * 
ds@1952
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1952
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1952
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1952
    15
 * details.
ds@1952
    16
 *
ds@1952
    17
 * You should have received a copy of the GNU General Public License along with
ds@1952
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
ds@1952
    19
 *
ds@1952
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1952
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1952
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1952
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1952
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1952
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1952
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1952
    27
 * or <http://www.sourcemod.net/license.php>.
ds@1952
    28
 *
ds@1952
    29
 * Version: $Id$
ds@1952
    30
 */
ds@1952
    31
ds@1952
    32
#include "sm_srvcmds.h"
ds@1952
    33
#include "sm_version.h"
ds@1952
    34
#include "sm_stringutil.h"
ds@1952
    35
#include "HandleSys.h"
ds@1952
    36
#include "CoreConfig.h"
ds@1952
    37
#include "ConVarManager.h"
ds@1952
    38
#include "ShareSys.h"
ds@1952
    39
ds@1952
    40
RootConsoleMenu g_RootMenu;
ds@1952
    41
ds@1952
    42
ConVar sourcemod_version("sourcemod_version", SVN_FULL_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");
ds@1952
    43
ds@1952
    44
RootConsoleMenu::RootConsoleMenu()
ds@1952
    45
{
ds@1952
    46
	m_pCommands = sm_trie_create();
ds@1952
    47
	m_CfgExecDone = false;
ds@1952
    48
}
ds@1952
    49
ds@1952
    50
RootConsoleMenu::~RootConsoleMenu()
ds@1952
    51
{
ds@1952
    52
	sm_trie_destroy(m_pCommands);
ds@1952
    53
ds@1952
    54
	List<ConsoleEntry *>::iterator iter;
ds@1952
    55
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
ds@1952
    56
	{
ds@1952
    57
		delete (*iter);
ds@1952
    58
	}
ds@1952
    59
	m_Menu.clear();
ds@1952
    60
}
ds@1952
    61
ds@1952
    62
void RootConsoleMenu::OnSourceModStartup(bool late)
ds@1952
    63
{
ds@1952
    64
#if defined ORANGEBOX_BUILD
ds@1952
    65
	g_pCVar = icvar;
ds@1952
    66
#endif
ds@1952
    67
	CONVAR_REGISTER(this);
ds@1952
    68
	AddRootConsoleCommand("version", "Display version information", this);
ds@1952
    69
	AddRootConsoleCommand("credits", "Display credits listing", this);
ds@1952
    70
}
ds@1952
    71
ds@1952
    72
void RootConsoleMenu::OnSourceModAllInitialized()
ds@1952
    73
{
ds@1952
    74
	g_ShareSys.AddInterface(NULL, this);
ds@1952
    75
}
ds@1952
    76
ds@1952
    77
void RootConsoleMenu::OnSourceModShutdown()
ds@1952
    78
{
ds@1952
    79
	RemoveRootConsoleCommand("credits", this);
ds@1952
    80
	RemoveRootConsoleCommand("version", this);
ds@1952
    81
}
ds@1952
    82
ds@1952
    83
bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
ds@1952
    84
{
ds@1952
    85
	META_REGCVAR(pCommand);
ds@1952
    86
ds@1952
    87
	/* Override values of convars created by SourceMod convar manager if specified on command line */
ds@1952
    88
	const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName());
ds@1952
    89
	if (cmdLineValue && !pCommand->IsCommand())
ds@1952
    90
	{
ds@1952
    91
		static_cast<ConVar *>(pCommand)->SetValue(cmdLineValue);
ds@1952
    92
	}
ds@1952
    93
ds@1952
    94
	return true;
ds@1952
    95
}
ds@1952
    96
ds@1952
    97
void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
ds@1952
    98
{
ds@1952
    99
	char buffer[512];
ds@1952
   100
ds@1952
   101
	va_list ap;
ds@1952
   102
	va_start(ap, fmt);
ds@1952
   103
	size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
ds@1952
   104
	va_end(ap);
ds@1952
   105
ds@1952
   106
	if (len >= sizeof(buffer) - 1)
ds@1952
   107
	{
ds@1952
   108
		buffer[510] = '\n';
ds@1952
   109
		buffer[511] = '\0';
ds@1952
   110
	} else {
ds@1952
   111
		buffer[len++] = '\n';
ds@1952
   112
		buffer[len] = '\0';
ds@1952
   113
	}
ds@1952
   114
	
ds@1952
   115
	META_CONPRINT(buffer);
ds@1952
   116
}
ds@1952
   117
ds@1952
   118
bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
ds@1952
   119
{
ds@1952
   120
	if (sm_trie_retrieve(m_pCommands, cmd, NULL))
ds@1952
   121
	{
ds@1952
   122
		return false;
ds@1952
   123
	}
ds@1952
   124
ds@1952
   125
	sm_trie_insert(m_pCommands, cmd, pHandler);
ds@1952
   126
ds@1952
   127
	/* Sort this into the menu */
ds@1952
   128
	List<ConsoleEntry *>::iterator iter = m_Menu.begin();
ds@1952
   129
	ConsoleEntry *pEntry;
ds@1952
   130
	bool inserted = false;
ds@1952
   131
	while (iter != m_Menu.end())
ds@1952
   132
	{
ds@1952
   133
		pEntry = (*iter);
ds@1952
   134
		if (strcmp(cmd, pEntry->command.c_str()) < 0)
ds@1952
   135
		{
ds@1952
   136
			ConsoleEntry *pNew = new ConsoleEntry;
ds@1952
   137
			pNew->command.assign(cmd);
ds@1952
   138
			pNew->description.assign(text);
ds@1952
   139
			m_Menu.insert(iter, pNew);
ds@1952
   140
			inserted = true;
ds@1952
   141
			break;
ds@1952
   142
		}
ds@1952
   143
		iter++;
ds@1952
   144
	}
ds@1952
   145
ds@1952
   146
	if (!inserted)
ds@1952
   147
	{
ds@1952
   148
		ConsoleEntry *pNew = new ConsoleEntry;
ds@1952
   149
		pNew->command.assign(cmd);
ds@1952
   150
		pNew->description.assign(text);
ds@1952
   151
		m_Menu.push_back(pNew);
ds@1952
   152
	}
ds@1952
   153
ds@1952
   154
	return true;
ds@1952
   155
}
ds@1952
   156
ds@1952
   157
bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
ds@1952
   158
{
ds@1952
   159
	/* Sanity tests */
ds@1952
   160
	IRootConsoleCommand *object;
ds@1952
   161
	if (sm_trie_retrieve(m_pCommands, cmd, (void **)&object))
ds@1952
   162
	{
ds@1952
   163
		if (object != pHandler)
ds@1952
   164
		{
ds@1952
   165
			return false;
ds@1952
   166
		}
ds@1952
   167
	} else {
ds@1952
   168
		return false;
ds@1952
   169
	}
ds@1952
   170
ds@1952
   171
	sm_trie_delete(m_pCommands, cmd);
ds@1952
   172
ds@1952
   173
	List<ConsoleEntry *>::iterator iter;
ds@1952
   174
	ConsoleEntry *pEntry;
ds@1952
   175
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
ds@1952
   176
	{
ds@1952
   177
		pEntry = (*iter);
ds@1952
   178
		if (pEntry->command.compare(cmd) == 0)
ds@1952
   179
		{
ds@1952
   180
			delete pEntry;
ds@1952
   181
			m_Menu.erase(iter);
ds@1952
   182
			break;
ds@1952
   183
		}
ds@1952
   184
	}
ds@1952
   185
ds@1952
   186
	return true;
ds@1952
   187
}
ds@1952
   188
ds@1952
   189
void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
ds@1952
   190
{
ds@1952
   191
	char buffer[255];
ds@1952
   192
	size_t len, cmdlen = strlen(cmd);
ds@1952
   193
ds@1952
   194
	len = UTIL_Format(buffer, sizeof(buffer), "    %s", cmd);
ds@1952
   195
	if (cmdlen < 16)
ds@1952
   196
	{
ds@1952
   197
		size_t num = 16 - cmdlen;
ds@1952
   198
		for (size_t i = 0; i < num; i++)
ds@1952
   199
		{
ds@1952
   200
			buffer[len++] = ' ';
ds@1952
   201
		}
ds@1952
   202
		len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
ds@1952
   203
		ConsolePrint("%s", buffer);
ds@1952
   204
	}
ds@1952
   205
}
ds@1952
   206
ds@1952
   207
const char *RootConsoleMenu::GetInterfaceName()
ds@1952
   208
{
ds@1952
   209
	return SMINTERFACE_ROOTCONSOLE_NAME;
ds@1952
   210
}
ds@1952
   211
ds@1952
   212
unsigned int RootConsoleMenu::GetInterfaceVersion()
ds@1952
   213
{
ds@1952
   214
	return SMINTERFACE_ROOTCONSOLE_VERSION;
ds@1952
   215
}
ds@1952
   216
ds@1952
   217
void RootConsoleMenu::GotRootCmd(const CCommand &cmd)
ds@1952
   218
{
ds@1952
   219
	unsigned int argnum = cmd.ArgC();
ds@1952
   220
ds@1952
   221
	if (argnum >= 2)
ds@1952
   222
	{
ds@1952
   223
		const char *cmdname = cmd.Arg(1);
ds@1952
   224
		if (strcmp(cmdname, "internal") == 0)
ds@1952
   225
		{
ds@1952
   226
			if (argnum >= 3)
ds@1952
   227
			{
ds@1952
   228
				const char *arg = cmd.Arg(2);
ds@1952
   229
				if (strcmp(arg, "1") == 0)
ds@1952
   230
				{
ds@1952
   231
					SM_ConfigsExecuted_Global();
ds@1952
   232
				}
ds@1952
   233
				else if (strcmp(arg, "2") == 0)
ds@1952
   234
				{
ds@1952
   235
					if (argnum >= 4)
ds@1952
   236
					{
ds@1952
   237
						SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3)));
ds@1952
   238
					}
ds@1952
   239
				}
ds@1952
   240
			}
ds@1952
   241
			return;
ds@1952
   242
		}
ds@1952
   243
ds@1952
   244
		IRootConsoleCommand *pHandler;
ds@1952
   245
		if (sm_trie_retrieve(m_pCommands, cmdname, (void **)&pHandler))
ds@1952
   246
		{
ds@1952
   247
			pHandler->OnRootConsoleCommand(cmdname, cmd);
ds@1952
   248
			return;
ds@1952
   249
		}
ds@1952
   250
	}
ds@1952
   251
ds@1952
   252
	ConsolePrint("SourceMod Menu:");
ds@1952
   253
	ConsolePrint("Usage: sm <command> [arguments]");
ds@1952
   254
ds@1952
   255
	List<ConsoleEntry *>::iterator iter;
ds@1952
   256
	ConsoleEntry *pEntry;
ds@1952
   257
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
ds@1952
   258
	{
ds@1952
   259
		pEntry = (*iter);
ds@1952
   260
		DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
ds@1952
   261
	}
ds@1952
   262
}
ds@1952
   263
ds@1952
   264
void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
ds@1952
   265
{
ds@1952
   266
	if (strcmp(cmdname, "credits") == 0)
ds@1952
   267
	{
ds@1952
   268
		ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
ds@1952
   269
		ConsolePrint(" Development would not have been possible without the following people:");
ds@1952
   270
		ConsolePrint("  David \"BAILOPAN\" Anderson, lead developer");
dvander@2105
   271
		ConsolePrint("  Borja \"faluco\" Ferrer, core developer");
dvander@2105
   272
		ConsolePrint("  Scott \"Damaged Soul\" Ehlert, core developer");
dvander@2105
   273
		ConsolePrint("  Matt \"pRED\" Woodrow, core developer");
dvander@2105
   274
		ConsolePrint("  Michael \"ferret\" McKoy, plugin developer");
ds@1952
   275
		ConsolePrint("  Pavol \"PM OnoTo\" Marko, SourceHook developer");
ds@1952
   276
		ConsolePrint(" Special thanks to Viper of GameConnect");
ds@1952
   277
		ConsolePrint(" Special thanks to Mani of Mani-Admin-Plugin");
ds@1952
   278
		ConsolePrint(" http://www.sourcemod.net/");
dvander@2105
   279
	}
dvander@2105
   280
	else if (strcmp(cmdname, "version") == 0)
dvander@2105
   281
	{
ds@1952
   282
		ConsolePrint(" SourceMod Version Information:");
ds@1952
   283
		ConsolePrint("    SourceMod Version: %s", SVN_FULL_VERSION);
ds@1952
   284
		ConsolePrint("    JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
ds@1952
   285
		ConsolePrint("    JIT Settings: %s", g_pVM->GetCPUOptimizations());
dvander@2105
   286
		ConsolePrint("    Compiled on: %s %s", __DATE__, __TIME__);
ds@1952
   287
		ConsolePrint("    http://www.sourcemod.net/");
ds@1952
   288
	}
ds@1952
   289
}
ds@1952
   290
ds@1952
   291
CON_COMMAND(sm, "SourceMod Menu")
ds@1952
   292
{
ds@1952
   293
#if !defined ORANGEBOX_BUILD
ds@1952
   294
	CCommand args;
ds@1952
   295
#endif
ds@1952
   296
	g_RootMenu.GotRootCmd(args);
ds@1952
   297
}
ds@1952
   298
ds@1952
   299
FILE *g_pHndlLog = NULL;
ds@1952
   300
ds@1952
   301
void write_handles_to_log(const char *fmt, ...)
ds@1952
   302
{
ds@1952
   303
	va_list ap;
ds@1952
   304
	
ds@1952
   305
	va_start(ap, fmt);
ds@1952
   306
	vfprintf(g_pHndlLog, fmt, ap);
ds@1952
   307
	fprintf(g_pHndlLog, "\n");
ds@1952
   308
	va_end(ap);
ds@1952
   309
}
ds@1952
   310
ds@1952
   311
void write_handles_to_game(const char *fmt, ...)
ds@1952
   312
{
ds@1952
   313
	size_t len;
ds@1952
   314
	va_list ap;
ds@1952
   315
	char buffer[1024];
ds@1952
   316
	
ds@1952
   317
	va_start(ap, fmt);
ds@1952
   318
	len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap);
ds@1952
   319
	va_end(ap);
ds@1952
   320
ds@1952
   321
	buffer[len] = '\n';
ds@1952
   322
	buffer[len+1] = '\0';
ds@1952
   323
ds@1952
   324
	engine->LogPrint(buffer);
ds@1952
   325
}
ds@1952
   326
ds@1952
   327
CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
ds@1952
   328
{
ds@1952
   329
#if !defined ORANGEBOX_BUILD
ds@1952
   330
	CCommand args;
ds@1952
   331
#endif
ds@1952
   332
	if (args.ArgC() < 2)
ds@1952
   333
	{
ds@1952
   334
		g_RootMenu.ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
ds@1952
   335
		return;
ds@1952
   336
	}
ds@1952
   337
ds@1952
   338
	if (strcmp(args.Arg(1), "log") != 0)
ds@1952
   339
	{
ds@1952
   340
		const char *arg = args.Arg(1);
ds@1952
   341
		FILE *fp = fopen(arg, "wt");
ds@1952
   342
		if (!fp)
ds@1952
   343
		{
ds@1952
   344
			g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
ds@1952
   345
			return;
ds@1952
   346
		}
ds@1952
   347
ds@1952
   348
		g_pHndlLog = fp;
ds@1952
   349
		g_HandleSys.Dump(write_handles_to_log);
ds@1952
   350
		g_pHndlLog = NULL;
ds@1952
   351
ds@1952
   352
		fclose(fp);
ds@1952
   353
	}
ds@1952
   354
	else
ds@1952
   355
	{
ds@1952
   356
		g_HandleSys.Dump(write_handles_to_game);
ds@1952
   357
	}
ds@1952
   358
}