core/sm_srvcmds.cpp
author David Anderson <dvander@alliedmods.net>
Wed Feb 27 13:49:57 2008 +0000 (2008-02-27)
changeset 1900 457329ae65bd
parent 1883 c9705da6f066
child 1902 ce912ad912a5
permissions -rw-r--r--
fixed amb1483 - GetEntPropString() rejected FIELD_MODELNAME/FIELD_SOUNDNAME
dvander@370
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 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@270
    33
#include "sm_version.h"
faluco@274
    34
#include "sm_stringutil.h"
dvander@900
    35
#include "HandleSys.h"
dvander@978
    36
#include "CoreConfig.h"
dvander@1770
    37
#include "ConVarManager.h"
dvander@1883
    38
#include "ShareSys.h"
faluco@216
    39
dvander@308
    40
RootConsoleMenu g_RootMenu;
faluco@216
    41
dvander@566
    42
ConVar sourcemod_version("sourcemod_version", SVN_FULL_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");
dvander@524
    43
dvander@308
    44
RootConsoleMenu::RootConsoleMenu()
faluco@216
    45
{
dvander@308
    46
	m_pCommands = sm_trie_create();
dvander@978
    47
	m_CfgExecDone = false;
faluco@216
    48
}
faluco@216
    49
dvander@308
    50
RootConsoleMenu::~RootConsoleMenu()
dvander@308
    51
{
dvander@308
    52
	sm_trie_destroy(m_pCommands);
dvander@308
    53
dvander@308
    54
	List<ConsoleEntry *>::iterator iter;
dvander@308
    55
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
    56
	{
dvander@308
    57
		delete (*iter);
dvander@308
    58
	}
dvander@308
    59
	m_Menu.clear();
dvander@308
    60
}
dvander@308
    61
dvander@1770
    62
extern void _IntExt_OnHostnameChanged(ConVar *var, const char *pOldValue, float flOldValue);
dvander@1770
    63
dvander@1770
    64
class DetectHostNameChanges : public IConVarChangeListener
dvander@1770
    65
{
dvander@1770
    66
public:
dvander@1770
    67
	void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
dvander@1770
    68
	{
dvander@1770
    69
		_IntExt_OnHostnameChanged(pConVar, oldValue, flOldValue);
dvander@1770
    70
	}
dvander@1770
    71
} s_HostnameChangeDetector;
ds@627
    72
dvander@308
    73
void RootConsoleMenu::OnSourceModStartup(bool late)
dvander@308
    74
{
faluco@1541
    75
#if defined ORANGEBOX_BUILD
dvander@1542
    76
	g_pCVar = icvar;
faluco@1541
    77
#endif
faluco@1541
    78
	CONVAR_REGISTER(this);
dvander@308
    79
	AddRootConsoleCommand("version", "Display version information", this);
dvander@308
    80
	AddRootConsoleCommand("credits", "Display credits listing", this);
dvander@1770
    81
}
ds@627
    82
dvander@1770
    83
void RootConsoleMenu::OnSourceModAllInitialized()
dvander@1770
    84
{
dvander@1770
    85
	g_ConVarManager.AddConVarChangeListener("hostname", &s_HostnameChangeDetector);
dvander@1883
    86
	g_ShareSys.AddInterface(NULL, this);
dvander@308
    87
}
dvander@308
    88
dvander@308
    89
void RootConsoleMenu::OnSourceModShutdown()
dvander@308
    90
{
dvander@1770
    91
	g_ConVarManager.RemoveConVarChangeListener("hostname", &s_HostnameChangeDetector);
dvander@308
    92
	RemoveRootConsoleCommand("credits", this);
dvander@308
    93
	RemoveRootConsoleCommand("version", this);
dvander@308
    94
}
dvander@308
    95
dvander@308
    96
bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
faluco@216
    97
{
faluco@216
    98
	META_REGCVAR(pCommand);
faluco@216
    99
ds@657
   100
	/* Override values of convars created by SourceMod convar manager if specified on command line */
ds@657
   101
	const char *cmdLineValue = icvar->GetCommandLineValue(pCommand->GetName());
ds@657
   102
	if (cmdLineValue && !pCommand->IsCommand())
ds@657
   103
	{
ds@657
   104
		static_cast<ConVar *>(pCommand)->SetValue(cmdLineValue);
ds@657
   105
	}
ds@657
   106
faluco@216
   107
	return true;
faluco@216
   108
}
faluco@216
   109
dvander@308
   110
void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
dvander@308
   111
{
dvander@308
   112
	char buffer[512];
dvander@308
   113
dvander@308
   114
	va_list ap;
dvander@308
   115
	va_start(ap, fmt);
dvander@308
   116
	size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
dvander@308
   117
	va_end(ap);
dvander@308
   118
dvander@324
   119
	if (len >= sizeof(buffer) - 1)
dvander@308
   120
	{
dvander@308
   121
		buffer[510] = '\n';
dvander@308
   122
		buffer[511] = '\0';
dvander@308
   123
	} else {
dvander@308
   124
		buffer[len++] = '\n';
dvander@308
   125
		buffer[len] = '\0';
dvander@308
   126
	}
dvander@308
   127
	
dvander@308
   128
	META_CONPRINT(buffer);
dvander@308
   129
}
dvander@308
   130
dvander@308
   131
bool RootConsoleMenu::AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler)
faluco@216
   132
{
dvander@308
   133
	if (sm_trie_retrieve(m_pCommands, cmd, NULL))
dvander@308
   134
	{
dvander@308
   135
		return false;
dvander@308
   136
	}
dvander@308
   137
dvander@308
   138
	sm_trie_insert(m_pCommands, cmd, pHandler);
dvander@308
   139
dvander@308
   140
	/* Sort this into the menu */
dvander@308
   141
	List<ConsoleEntry *>::iterator iter = m_Menu.begin();
dvander@308
   142
	ConsoleEntry *pEntry;
dvander@308
   143
	bool inserted = false;
dvander@308
   144
	while (iter != m_Menu.end())
dvander@308
   145
	{
dvander@308
   146
		pEntry = (*iter);
dvander@308
   147
		if (strcmp(cmd, pEntry->command.c_str()) < 0)
dvander@308
   148
		{
dvander@308
   149
			ConsoleEntry *pNew = new ConsoleEntry;
dvander@308
   150
			pNew->command.assign(cmd);
dvander@308
   151
			pNew->description.assign(text);
dvander@308
   152
			m_Menu.insert(iter, pNew);
dvander@308
   153
			inserted = true;
dvander@308
   154
			break;
dvander@308
   155
		}
dvander@308
   156
		iter++;
dvander@308
   157
	}
dvander@308
   158
dvander@308
   159
	if (!inserted)
dvander@308
   160
	{
dvander@308
   161
		ConsoleEntry *pNew = new ConsoleEntry;
dvander@308
   162
		pNew->command.assign(cmd);
dvander@308
   163
		pNew->description.assign(text);
dvander@308
   164
		m_Menu.push_back(pNew);
dvander@308
   165
	}
dvander@308
   166
dvander@308
   167
	return true;
dvander@308
   168
}
dvander@308
   169
dvander@308
   170
bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler)
dvander@308
   171
{
dvander@308
   172
	/* Sanity tests */
dvander@308
   173
	IRootConsoleCommand *object;
dvander@308
   174
	if (sm_trie_retrieve(m_pCommands, cmd, (void **)&object))
dvander@308
   175
	{
dvander@308
   176
		if (object != pHandler)
dvander@308
   177
		{
dvander@308
   178
			return false;
dvander@308
   179
		}
dvander@308
   180
	} else {
dvander@308
   181
		return false;
dvander@308
   182
	}
dvander@308
   183
dvander@308
   184
	sm_trie_delete(m_pCommands, cmd);
dvander@308
   185
dvander@308
   186
	List<ConsoleEntry *>::iterator iter;
dvander@308
   187
	ConsoleEntry *pEntry;
dvander@308
   188
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
   189
	{
dvander@308
   190
		pEntry = (*iter);
dvander@308
   191
		if (pEntry->command.compare(cmd) == 0)
dvander@308
   192
		{
dvander@308
   193
			delete pEntry;
dvander@308
   194
			m_Menu.erase(iter);
dvander@308
   195
			break;
dvander@308
   196
		}
dvander@308
   197
	}
dvander@308
   198
dvander@308
   199
	return true;
dvander@308
   200
}
dvander@308
   201
dvander@309
   202
void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
dvander@309
   203
{
dvander@309
   204
	char buffer[255];
dvander@309
   205
	size_t len, cmdlen = strlen(cmd);
dvander@309
   206
faluco@651
   207
	len = UTIL_Format(buffer, sizeof(buffer), "    %s", cmd);
dvander@309
   208
	if (cmdlen < 16)
dvander@309
   209
	{
dvander@309
   210
		size_t num = 16 - cmdlen;
dvander@309
   211
		for (size_t i = 0; i < num; i++)
dvander@309
   212
		{
dvander@309
   213
			buffer[len++] = ' ';
dvander@309
   214
		}
dvander@309
   215
		len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
dvander@309
   216
		ConsolePrint("%s", buffer);
dvander@309
   217
	}
dvander@309
   218
}
dvander@309
   219
dvander@1883
   220
const char *RootConsoleMenu::GetInterfaceName()
dvander@1883
   221
{
dvander@1883
   222
	return SMINTERFACE_ROOTCONSOLE_NAME;
dvander@1883
   223
}
dvander@1883
   224
dvander@1883
   225
unsigned int RootConsoleMenu::GetInterfaceVersion()
dvander@1883
   226
{
dvander@1883
   227
	return SMINTERFACE_ROOTCONSOLE_VERSION;
dvander@1883
   228
}
dvander@1883
   229
dvander@614
   230
extern void _IntExt_EnableYams();
dvander@614
   231
faluco@1541
   232
void RootConsoleMenu::GotRootCmd(const CCommand &cmd)
dvander@308
   233
{
faluco@1541
   234
	unsigned int argnum = cmd.ArgC();
faluco@216
   235
faluco@216
   236
	if (argnum >= 2)
faluco@216
   237
	{
faluco@1541
   238
		const char *cmdname = cmd.Arg(1);
faluco@1541
   239
		if (strcmp(cmdname, "text") == 0)
dvander@614
   240
		{
dvander@614
   241
			_IntExt_EnableYams();
dvander@614
   242
			return;
dvander@1630
   243
		}
dvander@1630
   244
		else if (strcmp(cmdname, "internal") == 0)
dvander@1630
   245
		{
dvander@978
   246
			if (argnum >= 3)
dvander@978
   247
			{
faluco@1541
   248
				const char *arg = cmd.Arg(2);
dvander@978
   249
				if (strcmp(arg, "1") == 0)
dvander@978
   250
				{
dvander@978
   251
					SM_ConfigsExecuted_Global();
dvander@1630
   252
				}
dvander@1630
   253
				else if (strcmp(arg, "2") == 0)
dvander@1630
   254
				{
dvander@978
   255
					if (argnum >= 4)
dvander@978
   256
					{
faluco@1541
   257
						SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3)));
dvander@978
   258
					}
dvander@978
   259
				}
dvander@978
   260
			}
dvander@978
   261
			return;
dvander@614
   262
		}
dvander@978
   263
dvander@308
   264
		IRootConsoleCommand *pHandler;
faluco@1541
   265
		if (sm_trie_retrieve(m_pCommands, cmdname, (void **)&pHandler))
faluco@216
   266
		{
faluco@1541
   267
			pHandler->OnRootConsoleCommand(cmdname, cmd);
faluco@270
   268
			return;
faluco@216
   269
		}
faluco@216
   270
	}
dvander@308
   271
dvander@308
   272
	ConsolePrint("SourceMod Menu:");
dvander@308
   273
	ConsolePrint("Usage: sm <command> [arguments]");
dvander@308
   274
dvander@308
   275
	List<ConsoleEntry *>::iterator iter;
dvander@308
   276
	ConsoleEntry *pEntry;
dvander@308
   277
	for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
dvander@308
   278
	{
dvander@308
   279
		pEntry = (*iter);
dvander@309
   280
		DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
dvander@308
   281
	}
dvander@308
   282
}
dvander@308
   283
faluco@1541
   284
void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
dvander@308
   285
{
faluco@1541
   286
	if (strcmp(cmdname, "credits") == 0)
dvander@308
   287
	{
dvander@308
   288
		ConsolePrint(" SourceMod was developed by AlliedModders, LLC.");
dvander@308
   289
		ConsolePrint(" Development would not have been possible without the following people:");
dvander@308
   290
		ConsolePrint("  David \"BAILOPAN\" Anderson, lead developer");
dvander@308
   291
		ConsolePrint("  Borja \"faluco\" Ferrer, Core developer");
ds@626
   292
		ConsolePrint("  Scott \"Damaged Soul\" Ehlert, Core developer");
dvander@308
   293
		ConsolePrint("  Pavol \"PM OnoTo\" Marko, SourceHook developer");
dvander@308
   294
		ConsolePrint(" Special thanks to Viper of GameConnect");
dvander@308
   295
		ConsolePrint(" Special thanks to Mani of Mani-Admin-Plugin");
dvander@308
   296
		ConsolePrint(" http://www.sourcemod.net/");
faluco@1541
   297
	} else if (strcmp(cmdname, "version") == 0) {
dvander@308
   298
		ConsolePrint(" SourceMod Version Information:");
dvander@566
   299
		ConsolePrint("    SourceMod Version: %s", SVN_FULL_VERSION);
dvander@308
   300
		ConsolePrint("    JIT Version: %s, %s", g_pVM->GetVMName(), g_pVM->GetVersionString());
dvander@308
   301
		ConsolePrint("    JIT Settings: %s", g_pVM->GetCPUOptimizations());
dvander@308
   302
		ConsolePrint("    http://www.sourcemod.net/");
dvander@308
   303
	}
dvander@308
   304
}
dvander@308
   305
dvander@308
   306
CON_COMMAND(sm, "SourceMod Menu")
dvander@308
   307
{
faluco@1541
   308
#if !defined ORANGEBOX_BUILD
faluco@1541
   309
	CCommand args;
faluco@1541
   310
#endif
faluco@1541
   311
	g_RootMenu.GotRootCmd(args);
dvander@308
   312
}
dvander@900
   313
dvander@1687
   314
FILE *g_pHndlLog = NULL;
dvander@1687
   315
dvander@1687
   316
void write_handles_to_log(const char *fmt, ...)
dvander@1687
   317
{
dvander@1687
   318
	va_list ap;
dvander@1687
   319
	
dvander@1687
   320
	va_start(ap, fmt);
dvander@1687
   321
	vfprintf(g_pHndlLog, fmt, ap);
dvander@1687
   322
	fprintf(g_pHndlLog, "\n");
dvander@1687
   323
	va_end(ap);
dvander@1687
   324
}
dvander@1687
   325
dvander@1687
   326
void write_handles_to_game(const char *fmt, ...)
dvander@1687
   327
{
dvander@1687
   328
	size_t len;
dvander@1687
   329
	va_list ap;
dvander@1687
   330
	char buffer[1024];
dvander@1687
   331
	
dvander@1687
   332
	va_start(ap, fmt);
dvander@1687
   333
	len = UTIL_FormatArgs(buffer, sizeof(buffer)-2, fmt, ap);
dvander@1687
   334
	va_end(ap);
dvander@1687
   335
dvander@1687
   336
	buffer[len] = '\n';
dvander@1687
   337
	buffer[len+1] = '\0';
dvander@1687
   338
dvander@1687
   339
	engine->LogPrint(buffer);
dvander@1687
   340
}
dvander@1687
   341
dvander@900
   342
CON_COMMAND(sm_dump_handles, "Dumps Handle usage to a file for finding Handle leaks")
dvander@900
   343
{
faluco@1541
   344
#if !defined ORANGEBOX_BUILD
faluco@1541
   345
	CCommand args;
faluco@1541
   346
#endif
faluco@1541
   347
	if (args.ArgC() < 2)
dvander@900
   348
	{
dvander@1687
   349
		g_RootMenu.ConsolePrint("Usage: sm_dump_handles <file> or <log> for game logs");
dvander@900
   350
		return;
dvander@900
   351
	}
dvander@900
   352
dvander@1687
   353
	if (strcmp(args.Arg(1), "log") != 0)
dvander@900
   354
	{
dvander@1687
   355
		const char *arg = args.Arg(1);
dvander@1687
   356
		FILE *fp = fopen(arg, "wt");
dvander@1687
   357
		if (!fp)
dvander@1687
   358
		{
dvander@1687
   359
			g_RootMenu.ConsolePrint("Could not find file \"%s\"", arg);
dvander@1687
   360
			return;
dvander@1687
   361
		}
dvander@900
   362
dvander@1687
   363
		g_pHndlLog = fp;
dvander@1687
   364
		g_HandleSys.Dump(write_handles_to_log);
dvander@1687
   365
		g_pHndlLog = NULL;
dvander@900
   366
dvander@1687
   367
		fclose(fp);
dvander@1687
   368
	}
dvander@1687
   369
	else
dvander@1687
   370
	{
dvander@1687
   371
		g_HandleSys.Dump(write_handles_to_game);
dvander@1687
   372
	}
dvander@900
   373
}