core/sm_srvcmds.cpp
author Peace-Maker <januk@freenet.de>
Wed Apr 23 08:55:09 2014 -0400 (2014-04-23)
changeset 4330 98726cea1607
parent 4306 f8a08c7f0c92
permissions -rw-r--r--
Mark CS:S as supporting HudMsg (bug 6108, r=psychonic).
dvander@370
     1
/**
dvander@4074
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@2728
     5
 * Copyright (C) 2004-2009 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
faluco@216
    32
#include "sm_srvcmds.h"
faluco@274
    33
#include "sm_stringutil.h"
dvander@978
    34
#include "CoreConfig.h"
dvander@1770
    35
#include "ConVarManager.h"
dvander@3872
    36
#include "logic_bridge.h"
dvander@4188
    37
#include <sourcemod_version.h>
faluco@216
    38
dvander@308
    39
RootConsoleMenu g_RootMenu;
faluco@216
    40
dvander@4188
    41
ConVar sourcemod_version("sourcemod_version", SOURCEMOD_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");
dvander@524
    42
dvander@308
    43
RootConsoleMenu::RootConsoleMenu()
faluco@216
    44
{
dvander@978
    45
	m_CfgExecDone = false;
faluco@216
    46
}
faluco@216
    47
dvander@308
    48
RootConsoleMenu::~RootConsoleMenu()
dvander@308
    49
{
dvander@308
    50
	List<ConsoleEntry *>::iterator iter;
dvander@308
    51
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
    52
	{
dvander@308
    53
		delete (*iter);
dvander@308
    54
	}
dvander@308
    55
	m_Menu.clear();
dvander@308
    56
}
dvander@308
    57
dvander@308
    58
void RootConsoleMenu::OnSourceModStartup(bool late)
dvander@308
    59
{
ds@2400
    60
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1542
    61
	g_pCVar = icvar;
faluco@1541
    62
#endif
faluco@1541
    63
	CONVAR_REGISTER(this);
dvander@308
    64
	AddRootConsoleCommand("version", "Display version information", this);
dvander@308
    65
	AddRootConsoleCommand("credits", "Display credits listing", this);
dvander@1770
    66
}
ds@627
    67
dvander@1770
    68
void RootConsoleMenu::OnSourceModAllInitialized()
dvander@1770
    69
{
dvander@3872
    70
	sharesys->AddInterface(NULL, this);
dvander@308
    71
}
dvander@308
    72
dvander@308
    73
void RootConsoleMenu::OnSourceModShutdown()
dvander@308
    74
{
dvander@308
    75
	RemoveRootConsoleCommand("credits", this);
dvander@308
    76
	RemoveRootConsoleCommand("version", this);
dvander@308
    77
}
dvander@308
    78
dvander@308
    79
bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
faluco@216
    80
{
faluco@216
    81
	META_REGCVAR(pCommand);
faluco@216
    82
ds@657
    83
	/* Override values of convars created by SourceMod convar manager if specified on command line */
ds@657
    84
	const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName());
ds@657
    85
	if (cmdLineValue && !pCommand->IsCommand())
ds@657
    86
	{
ds@657
    87
		static_cast<ConVar *>(pCommand)->SetValue(cmdLineValue);
ds@657
    88
	}
ds@657
    89
faluco@216
    90
	return true;
faluco@216
    91
}
faluco@216
    92
dvander@308
    93
void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
dvander@308
    94
{
dvander@308
    95
	char buffer[512];
dvander@308
    96
dvander@308
    97
	va_list ap;
dvander@308
    98
	va_start(ap, fmt);
dvander@308
    99
	size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
dvander@308
   100
	va_end(ap);
dvander@308
   101
dvander@324
   102
	if (len >= sizeof(buffer) - 1)
dvander@308
   103
	{
dvander@308
   104
		buffer[510] = '\n';
dvander@308
   105
		buffer[511] = '\0';
dvander@308
   106
	} else {
dvander@308
   107
		buffer[len++] = '\n';
dvander@308
   108
		buffer[len] = '\0';
dvander@308
   109
	}
dvander@308
   110
	
dvander@308
   111
	META_CONPRINT(buffer);
dvander@308
   112
}
dvander@308
   113
dvander@308
   114
bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
faluco@216
   115
{
dvander@2728
   116
	return _AddRootConsoleCommand(cmd, text, pHandler, false);
dvander@2728
   117
}
dvander@2728
   118
dvander@2728
   119
bool RootConsoleMenu::AddRootConsoleCommand2(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
dvander@2728
   120
{
dvander@2728
   121
	return _AddRootConsoleCommand(cmd, text, pHandler, true);
dvander@2728
   122
}
dvander@2728
   123
dvander@2728
   124
bool RootConsoleMenu::_AddRootConsoleCommand(const char *cmd,
dvander@2728
   125
											 const char *text,
dvander@2728
   126
											 IRootConsoleCommand *pHandler,
dvander@2728
   127
											 bool version2)
dvander@2728
   128
{
dvander@4074
   129
	if (m_Commands.contains(cmd))
dvander@308
   130
		return false;
dvander@308
   131
dvander@308
   132
	/* Sort this into the menu */
dvander@308
   133
	List<ConsoleEntry *>::iterator iter = m_Menu.begin();
dvander@308
   134
	ConsoleEntry *pEntry;
dvander@308
   135
	bool inserted = false;
dvander@308
   136
	while (iter != m_Menu.end())
dvander@308
   137
	{
dvander@308
   138
		pEntry = (*iter);
dvander@308
   139
		if (strcmp(cmd, pEntry->command.c_str()) < 0)
dvander@308
   140
		{
dvander@308
   141
			ConsoleEntry *pNew = new ConsoleEntry;
dvander@308
   142
			pNew->command.assign(cmd);
dvander@308
   143
			pNew->description.assign(text);
dvander@2728
   144
			pNew->version2 = version2;
dvander@2728
   145
			pNew->cmd = pHandler;
dvander@4074
   146
			m_Commands.insert(cmd, pNew);
dvander@308
   147
			m_Menu.insert(iter, pNew);
dvander@308
   148
			inserted = true;
dvander@308
   149
			break;
dvander@308
   150
		}
dvander@308
   151
		iter++;
dvander@308
   152
	}
dvander@308
   153
dvander@308
   154
	if (!inserted)
dvander@308
   155
	{
dvander@308
   156
		ConsoleEntry *pNew = new ConsoleEntry;
dvander@308
   157
		pNew->command.assign(cmd);
dvander@308
   158
		pNew->description.assign(text);
dvander@2728
   159
		pNew->version2 = version2;
dvander@2728
   160
		pNew->cmd = pHandler;
dvander@4074
   161
		m_Commands.insert(cmd, pNew);
dvander@308
   162
		m_Menu.push_back(pNew);
dvander@308
   163
	}
dvander@308
   164
dvander@308
   165
	return true;
dvander@308
   166
}
dvander@308
   167
dvander@308
   168
bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
dvander@308
   169
{
dvander@4074
   170
	m_Commands.remove(cmd);
dvander@308
   171
dvander@308
   172
	List<ConsoleEntry *>::iterator iter;
dvander@308
   173
	ConsoleEntry *pEntry;
dvander@308
   174
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
   175
	{
dvander@308
   176
		pEntry = (*iter);
dvander@308
   177
		if (pEntry->command.compare(cmd) == 0)
dvander@308
   178
		{
dvander@308
   179
			delete pEntry;
dvander@308
   180
			m_Menu.erase(iter);
dvander@308
   181
			break;
dvander@308
   182
		}
dvander@308
   183
	}
dvander@308
   184
dvander@308
   185
	return true;
dvander@308
   186
}
dvander@308
   187
dvander@309
   188
void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
dvander@309
   189
{
dvander@309
   190
	char buffer[255];
dvander@309
   191
	size_t len, cmdlen = strlen(cmd);
dvander@309
   192
faluco@651
   193
	len = UTIL_Format(buffer, sizeof(buffer), "    %s", cmd);
dvander@309
   194
	if (cmdlen < 16)
dvander@309
   195
	{
dvander@309
   196
		size_t num = 16 - cmdlen;
dvander@309
   197
		for (size_t i = 0; i < num; i++)
dvander@309
   198
		{
dvander@309
   199
			buffer[len++] = ' ';
dvander@309
   200
		}
dvander@309
   201
		len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
dvander@309
   202
		ConsolePrint("%s", buffer);
dvander@309
   203
	}
dvander@309
   204
}
dvander@309
   205
dvander@1883
   206
const char *RootConsoleMenu::GetInterfaceName()
dvander@1883
   207
{
dvander@1883
   208
	return SMINTERFACE_ROOTCONSOLE_NAME;
dvander@1883
   209
}
dvander@1883
   210
dvander@1883
   211
unsigned int RootConsoleMenu::GetInterfaceVersion()
dvander@1883
   212
{
dvander@1883
   213
	return SMINTERFACE_ROOTCONSOLE_VERSION;
dvander@1883
   214
}
dvander@1883
   215
dvander@2728
   216
#if SOURCE_ENGINE==SE_EPISODEONE || SOURCE_ENGINE==SE_DARKMESSIAH
dvander@2728
   217
class CCommandArgs : public ICommandArgs
dvander@2728
   218
{
dvander@2728
   219
public:
dvander@2728
   220
	CCommandArgs(const CCommand& _cmd)
dvander@2728
   221
	{
dvander@2728
   222
	}
dvander@2728
   223
	const char *Arg(int n) const
dvander@2728
   224
	{
dvander@2728
   225
		return engine->Cmd_Argv(n);
dvander@2728
   226
	}
dvander@2728
   227
	int ArgC() const
dvander@2728
   228
	{
dvander@2728
   229
		return engine->Cmd_Argc();
dvander@2728
   230
	}
dvander@2728
   231
	const char *ArgS() const
dvander@2728
   232
	{
dvander@2728
   233
		return engine->Cmd_Args();
dvander@2728
   234
	}
dvander@2728
   235
};
dvander@2728
   236
#else
dvander@2728
   237
class CCommandArgs : public ICommandArgs
dvander@2728
   238
{
dvander@2728
   239
	const CCommand *cmd;
dvander@2728
   240
public:
dvander@2728
   241
	CCommandArgs(const CCommand& _cmd) : cmd(&_cmd)
dvander@2728
   242
	{
dvander@2728
   243
	}
dvander@2728
   244
	const char *Arg(int n) const
dvander@2728
   245
	{
dvander@2728
   246
		return cmd->Arg(n);
dvander@2728
   247
	}
dvander@2728
   248
	int ArgC() const
dvander@2728
   249
	{
dvander@2728
   250
		return cmd->ArgC();
dvander@2728
   251
	}
dvander@2728
   252
	const char *ArgS() const
dvander@2728
   253
	{
dvander@2728
   254
		return cmd->ArgS();
dvander@2728
   255
	}
dvander@2728
   256
};
dvander@2728
   257
#endif
dvander@2728
   258
faluco@1541
   259
void RootConsoleMenu::GotRootCmd(const CCommand &cmd)
dvander@308
   260
{
faluco@1541
   261
	unsigned int argnum = cmd.ArgC();
faluco@216
   262
faluco@216
   263
	if (argnum >= 2)
faluco@216
   264
	{
faluco@1541
   265
		const char *cmdname = cmd.Arg(1);
dvander@1902
   266
		if (strcmp(cmdname, "internal") == 0)
dvander@1630
   267
		{
dvander@978
   268
			if (argnum >= 3)
dvander@978
   269
			{
faluco@1541
   270
				const char *arg = cmd.Arg(2);
dvander@978
   271
				if (strcmp(arg, "1") == 0)
dvander@978
   272
				{
dvander@978
   273
					SM_ConfigsExecuted_Global();
dvander@1630
   274
				}
dvander@1630
   275
				else if (strcmp(arg, "2") == 0)
dvander@1630
   276
				{
dvander@978
   277
					if (argnum >= 4)
dvander@978
   278
					{
faluco@1541
   279
						SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3)));
dvander@978
   280
					}
dvander@978
   281
				}
dvander@978
   282
			}
dvander@978
   283
			return;
dvander@614
   284
		}
dvander@978
   285
dvander@2728
   286
		CCommandArgs ocmd(cmd);
dvander@2728
   287
dvander@2728
   288
		ConsoleEntry *entry;
dvander@4074
   289
		if (m_Commands.retrieve(cmdname, &entry))
faluco@216
   290
		{
dvander@2728
   291
			if (entry->version2)
dvander@2728
   292
			{
dvander@2728
   293
				entry->cmd->OnRootConsoleCommand2(cmdname, &ocmd);
dvander@2728
   294
			}
dvander@2728
   295
			else
dvander@2728
   296
			{
dvander@2728
   297
				entry->cmd->OnRootConsoleCommand(cmdname, cmd);
dvander@2728
   298
			}
faluco@270
   299
			return;
faluco@216
   300
		}
faluco@216
   301
	}
dvander@308
   302
dvander@308
   303
	ConsolePrint("SourceMod Menu:");
dvander@308
   304
	ConsolePrint("Usage: sm <command> [arguments]");
dvander@308
   305
dvander@308
   306
	List<ConsoleEntry *>::iterator iter;
dvander@308
   307
	ConsoleEntry *pEntry;
dvander@308
   308
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
   309
	{
dvander@308
   310
		pEntry = (*iter);
dvander@309
   311
		DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
dvander@308
   312
	}
dvander@308
   313
}
dvander@308
   314
faluco@1541
   315
void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
dvander@308
   316
{
faluco@1541
   317
	if (strcmp(cmdname, "credits") == 0)
dvander@308
   318
	{
dvander@308
   319
		ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
dvander@308
   320
		ConsolePrint(" Development would not have been possible without the following people:");
dvander@2905
   321
		ConsolePrint("  David \"BAILOPAN\" Anderson");
dvander@2905
   322
		ConsolePrint("  Matt \"pRED\" Woodrow");
dvander@2905
   323
		ConsolePrint("  Scott \"DS\" Ehlert");
dvander@2905
   324
		ConsolePrint("  Fyren");
dvander@3311
   325
		ConsolePrint("  Nicholas \"psychonic\" Hastings");
asherkin@3621
   326
		ConsolePrint("  Asher \"asherkin\" Baker");
dvander@2905
   327
		ConsolePrint("  Borja \"faluco\" Ferrer");
dvander@2905
   328
		ConsolePrint("  Pavol \"PM OnoTo\" Marko");
asherkin@3621
   329
		ConsolePrint(" Special thanks to Liam, ferret, and Mani");
dvander@2905
   330
		ConsolePrint(" Special thanks to Viper and SteamFriends");
dvander@308
   331
		ConsolePrint(" http://www.sourcemod.net/");
dvander@2105
   332
	}
dvander@2105
   333
	else if (strcmp(cmdname, "version") == 0)
dvander@2105
   334
	{
dvander@308
   335
		ConsolePrint(" SourceMod Version Information:");
dvander@4188
   336
		ConsolePrint("    SourceMod Version: %s", SOURCEMOD_VERSION);
dvander@4116
   337
		if (g_pSourcePawn2->IsJitEnabled())
dvander@4116
   338
			ConsolePrint("    SourcePawn Engine: %s (build %s)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
dvander@4116
   339
		else
dvander@4116
   340
			ConsolePrint("    SourcePawn Engine: %s (build %s NO JIT)", g_pSourcePawn2->GetEngineName(), g_pSourcePawn2->GetVersionString());
dvander@2193
   341
		ConsolePrint("    SourcePawn API: v1 = %d, v2 = %d", g_pSourcePawn->GetEngineAPIVersion(), g_pSourcePawn2->GetAPIVersion());
dvander@2105
   342
		ConsolePrint("    Compiled on: %s %s", __DATE__, __TIME__);
dvander@4188
   343
		ConsolePrint("    Build ID: %s", SOURCEMOD_BUILD_ID);
dvander@308
   344
		ConsolePrint("    http://www.sourcemod.net/");
dvander@308
   345
	}
dvander@308
   346
}
dvander@308
   347
dvander@308
   348
CON_COMMAND(sm, "SourceMod Menu")
dvander@308
   349
{
ds@2583
   350
#if SOURCE_ENGINE <= SE_DARKMESSIAH
faluco@1541
   351
	CCommand args;
faluco@1541
   352
#endif
faluco@1541
   353
	g_RootMenu.GotRootCmd(args);
dvander@308
   354
}
dvander@900
   355
dvander@1687
   356
FILE *g_pHndlLog = NULL;
dvander@1687
   357
dvander@1687
   358
void write_handles_to_log(const char *fmt, ...)
dvander@1687
   359
{
dvander@1687
   360
	va_list ap;
dvander@1687
   361
	
dvander@1687
   362
	va_start(ap, fmt);
dvander@1687
   363
	vfprintf(g_pHndlLog, fmt, ap);
dvander@1687
   364
	fprintf(g_pHndlLog, "\n");
dvander@1687
   365
	va_end(ap);
dvander@1687
   366
}
dvander@1687
   367
dvander@1687
   368
void write_handles_to_game(const char *fmt, ...)
dvander@1687
   369
{
dvander@1687
   370
	size_t len;
dvander@1687
   371
	va_list ap;
dvander@1687
   372
	char buffer[1024];
dvander@1687
   373
	
dvander@1687
   374
	va_start(ap, fmt);
dvander@1687
   375
	len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap);
dvander@1687
   376
	va_end(ap);
dvander@1687
   377
dvander@1687
   378
	buffer[len] = '\n';
dvander@1687
   379
	buffer[len+1] = '\0';
dvander@1687
   380
dvander@1687
   381
	engine->LogPrint(buffer);
dvander@1687
   382
}
dvander@1687
   383
dvander@900
   384
CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
dvander@900
   385
{
ds@2583
   386
#if SOURCE_ENGINE <= SE_DARKMESSIAH
faluco@1541
   387
	CCommand args;
faluco@1541
   388
#endif
faluco@1541
   389
	if (args.ArgC() < 2)
dvander@900
   390
	{
dvander@1687
   391
		g_RootMenu.ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
dvander@900
   392
		return;
dvander@900
   393
	}
dvander@900
   394
dvander@1687
   395
	if (strcmp(args.Arg(1), "log") != 0)
dvander@900
   396
	{
dvander@1687
   397
		const char *arg = args.Arg(1);
dvander@1687
   398
		FILE *fp = fopen(arg, "wt");
dvander@1687
   399
		if (!fp)
dvander@1687
   400
		{
dvander@1687
   401
			g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
dvander@1687
   402
			return;
dvander@1687
   403
		}
dvander@900
   404
dvander@1687
   405
		g_pHndlLog = fp;
dvander@3872
   406
		logicore.DumpHandles(write_handles_to_log);
dvander@1687
   407
		g_pHndlLog = NULL;
dvander@900
   408
dvander@1687
   409
		fclose(fp);
dvander@1687
   410
	}
dvander@1687
   411
	else
dvander@1687
   412
	{
dvander@3872
   413
		logicore.DumpHandles(write_handles_to_game);
dvander@1687
   414
	}
dvander@900
   415
}
dvander@2728
   416
skamonkey@4306
   417
CON_COMMAND(sm_reload_translations, "Reparses all loaded translation files")
skamonkey@4306
   418
{
skamonkey@4306
   419
	translator->RebuildLanguageDatabase();
skamonkey@4306
   420
}
skamonkey@4306
   421