--HG-- rename : core/ForwardSys.cpp => core/logic/ForwardSys.cpp rename : core/ForwardSys.h => core/logic/ForwardSys.h
		
			
				
	
	
		
			1613 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1613 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * vim: set ts=4 sw=4 tw=99 noet :
 | 
						|
 * =============================================================================
 | 
						|
 * SourceMod
 | 
						|
 * Copyright (C) 2004-2010 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_globals.h"
 | 
						|
#include "sourcemod.h"
 | 
						|
#include "HalfLife2.h"
 | 
						|
#include "sourcemm_api.h"
 | 
						|
#include "ConVarManager.h"
 | 
						|
#include "ConCmdManager.h"
 | 
						|
#include "sm_stringutil.h"
 | 
						|
#include "PlayerManager.h"
 | 
						|
#include "ChatTriggers.h"
 | 
						|
#include "AdminCache.h"
 | 
						|
#include <inetchannel.h>
 | 
						|
#include <bitbuf.h>
 | 
						|
#include <tier0/dbg.h>
 | 
						|
#include "Logger.h"
 | 
						|
#include "ConsoleDetours.h"
 | 
						|
#include "ConCommandBaseIterator.h"
 | 
						|
#include "logic_bridge.h"
 | 
						|
#include <sm_namehashset.h>
 | 
						|
 | 
						|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
 | 
						|
#include <netmessages.pb.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#if SOURCE_ENGINE >= SE_EYE
 | 
						|
#define NETMSG_BITS 6
 | 
						|
#else
 | 
						|
#define NETMSG_BITS 5
 | 
						|
#endif
 | 
						|
 | 
						|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
 | 
						|
#define NET_SETCONVAR	6
 | 
						|
#else
 | 
						|
#define NET_SETCONVAR	5
 | 
						|
#endif
 | 
						|
 | 
						|
enum ConVarBounds
 | 
						|
{
 | 
						|
	ConVarBound_Upper = 0,
 | 
						|
	ConVarBound_Lower
 | 
						|
};
 | 
						|
 | 
						|
HandleType_t hCmdIterType = 0;
 | 
						|
HandleType_t htConCmdIter = 0;
 | 
						|
 | 
						|
struct GlobCmdIter
 | 
						|
{
 | 
						|
	bool started;
 | 
						|
	List<ConCmdInfo *>::iterator iter;
 | 
						|
};
 | 
						|
 | 
						|
class ConsoleHelpers : 
 | 
						|
	public SMGlobalClass,
 | 
						|
	public IHandleTypeDispatch
 | 
						|
{
 | 
						|
public:
 | 
						|
	virtual void OnSourceModAllInitialized()
 | 
						|
	{
 | 
						|
		HandleAccess access;
 | 
						|
 | 
						|
		handlesys->InitAccessDefaults(NULL, &access);
 | 
						|
 | 
						|
		htConCmdIter = handlesys->CreateType("ConCmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
 | 
						|
 | 
						|
		access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
 | 
						|
 | 
						|
		hCmdIterType = handlesys->CreateType("CmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
 | 
						|
	}
 | 
						|
	virtual void OnHandleDestroy(HandleType_t type, void *object)
 | 
						|
	{
 | 
						|
		if (type == hCmdIterType)
 | 
						|
		{
 | 
						|
			GlobCmdIter *iter = (GlobCmdIter *)object;
 | 
						|
			delete iter;
 | 
						|
		}
 | 
						|
		else if (type == htConCmdIter)
 | 
						|
		{
 | 
						|
			ConCommandBaseIterator *iter = (ConCommandBaseIterator * )object;
 | 
						|
			delete iter;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
 | 
						|
	{
 | 
						|
		if (type == htConCmdIter)
 | 
						|
		{
 | 
						|
			*pSize = sizeof(ConCommandBaseIterator);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else if (type == hCmdIterType)
 | 
						|
		{
 | 
						|
			*pSize = sizeof(GlobCmdIter);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
} s_ConsoleHelpers;
 | 
						|
 | 
						|
class CommandFlagsHelper : public IConCommandTracker
 | 
						|
{
 | 
						|
public:
 | 
						|
	void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
 | 
						|
	{
 | 
						|
		m_CmdFlags.remove(name);
 | 
						|
	}
 | 
						|
	bool GetFlags(const char *name, int *flags)
 | 
						|
	{
 | 
						|
		ConCommandBase *pCmd;
 | 
						|
		if (m_CmdFlags.retrieve(name, &pCmd))
 | 
						|
		{
 | 
						|
			TrackConCommandBase(pCmd, this);
 | 
						|
			*flags = pCmd->GetFlags();
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else if ((pCmd=FindCommandBase(name)))
 | 
						|
		{
 | 
						|
			m_CmdFlags.insert(name, pCmd);
 | 
						|
			TrackConCommandBase(pCmd, this);
 | 
						|
			*flags = pCmd->GetFlags();
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	bool SetFlags(const char *name, int flags)
 | 
						|
	{
 | 
						|
		ConCommandBase *pCmd;
 | 
						|
		if (m_CmdFlags.retrieve(name, &pCmd))
 | 
						|
		{
 | 
						|
			pCmd->SetFlags(flags);
 | 
						|
			TrackConCommandBase(pCmd, this);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else if ((pCmd=FindCommandBase(name)))
 | 
						|
		{
 | 
						|
			m_CmdFlags.insert(name, pCmd);
 | 
						|
			pCmd->SetFlags(flags);
 | 
						|
			TrackConCommandBase(pCmd, this);
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
	}
 | 
						|
private:
 | 
						|
	struct ConCommandPolicy
 | 
						|
	{
 | 
						|
		static inline bool matches(const char *name, ConCommandBase *base)
 | 
						|
		{
 | 
						|
			return strcmp(name, base->GetName()) == 0;
 | 
						|
		}
 | 
						|
	};
 | 
						|
	NameHashSet<ConCommandBase *, ConCommandPolicy> m_CmdFlags;
 | 
						|
} s_CommandFlagsHelper;
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_ORANGEBOX
 | 
						|
static void ReplicateConVar(ConVar *pConVar)
 | 
						|
{
 | 
						|
	int maxClients = g_Players.GetMaxClients();
 | 
						|
 | 
						|
	char data[256];
 | 
						|
	bf_write buffer(data, sizeof(data));
 | 
						|
 | 
						|
	buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
 | 
						|
	buffer.WriteByte(1);
 | 
						|
	buffer.WriteString(pConVar->GetName());
 | 
						|
	buffer.WriteString(pConVar->GetString());
 | 
						|
 | 
						|
	for (int i = 1; i <= maxClients; i++)
 | 
						|
	{
 | 
						|
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
 | 
						|
 | 
						|
		if (pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient())
 | 
						|
		{
 | 
						|
			if (INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i)))
 | 
						|
				netchan->SendData(buffer);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void NotifyConVar(ConVar *pConVar)
 | 
						|
{
 | 
						|
	IGameEvent *pEvent = gameevents->CreateEvent("server_cvar");
 | 
						|
	pEvent->SetString("cvarname", pConVar->GetName());
 | 
						|
	if (IsFlagSet(pConVar, FCVAR_PROTECTED))
 | 
						|
	{
 | 
						|
		pEvent->SetString("cvarvalue", "***PROTECTED***");
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		pEvent->SetString("cvarvalue", pConVar->GetString());
 | 
						|
	}
 | 
						|
 | 
						|
	gameevents->FireEvent(pEvent);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name, *defaultVal, *helpText;
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	// While the engine seems to accept a blank convar name, it causes a crash upon server quit
 | 
						|
	if (name == NULL || strcmp(name, "") == 0)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Convar with blank name is not permitted");
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->LocalToString(params[2], &defaultVal);
 | 
						|
	pContext->LocalToString(params[3], &helpText);
 | 
						|
 | 
						|
	bool hasMin = params[5] ? true : false;
 | 
						|
	bool hasMax = params[7] ? true : false;
 | 
						|
	float min = sp_ctof(params[6]);
 | 
						|
	float max = sp_ctof(params[8]);
 | 
						|
 | 
						|
	Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
 | 
						|
 | 
						|
	if (hndl == BAD_HANDLE)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name);
 | 
						|
	}
 | 
						|
 | 
						|
	return hndl;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	return g_ConVarManager.FindConVar(name);
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
 | 
						|
	}
 | 
						|
 | 
						|
	g_ConVarManager.HookConVarChange(pConVar, pFunction);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
 | 
						|
	}
 | 
						|
 | 
						|
	g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	return pConVar->GetBool();
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	return pConVar->GetInt();
 | 
						|
}
 | 
						|
 | 
						|
/* This handles both SetConVarBool() and SetConVarInt() */
 | 
						|
static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	pConVar->SetValue(params[2]);
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_ORANGEBOX
 | 
						|
	/* Should we replicate it? */
 | 
						|
	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
 | 
						|
	{
 | 
						|
		ReplicateConVar(pConVar);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Should we notify clients? */
 | 
						|
	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
 | 
						|
	{
 | 
						|
		NotifyConVar(pConVar);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
	
 | 
						|
	float value = pConVar->GetFloat();
 | 
						|
 | 
						|
	return sp_ftoc(value);
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	float value = sp_ctof(params[2]);
 | 
						|
	pConVar->SetValue(value);
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_ORANGEBOX
 | 
						|
	/* Should we replicate it? */
 | 
						|
	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
 | 
						|
	{
 | 
						|
		ReplicateConVar(pConVar);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Should we notify clients? */
 | 
						|
	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
 | 
						|
	{
 | 
						|
		NotifyConVar(pConVar);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	char *value;
 | 
						|
	pContext->LocalToString(params[2], &value);
 | 
						|
 | 
						|
	pConVar->SetValue(value);
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_ORANGEBOX
 | 
						|
	/* Should we replicate it? */
 | 
						|
	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
 | 
						|
	{
 | 
						|
		ReplicateConVar(pConVar);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Should we notify clients? */
 | 
						|
	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
 | 
						|
	{
 | 
						|
		NotifyConVar(pConVar);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	pConVar->Revert();
 | 
						|
	
 | 
						|
#if SOURCE_ENGINE < SE_ORANGEBOX
 | 
						|
	/* Should we replicate it? */
 | 
						|
	if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
 | 
						|
	{
 | 
						|
		ReplicateConVar(pConVar);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Should we notify clients? */
 | 
						|
	if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
 | 
						|
	{
 | 
						|
		NotifyConVar(pConVar);
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t GetConVarDefault(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	size_t bytes;
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetDefault(), &bytes);
 | 
						|
 | 
						|
	return bytes;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	return pConVar->GetFlags();
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	pConVar->SetFlags(params[2]);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarBounds(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	cell_t *addr;
 | 
						|
	bool hasBound;
 | 
						|
	float bound;
 | 
						|
 | 
						|
	switch (params[2])
 | 
						|
	{
 | 
						|
	case ConVarBound_Upper:
 | 
						|
		hasBound = pConVar->GetMax(bound);
 | 
						|
		break;
 | 
						|
	case ConVarBound_Lower:
 | 
						|
		hasBound = pConVar->GetMin(bound);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
 | 
						|
	}
 | 
						|
	
 | 
						|
	pContext->LocalToPhysAddr(params[3], &addr);
 | 
						|
	*addr = sp_ftoc(bound);
 | 
						|
 | 
						|
	return hasBound;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	switch (params[2])
 | 
						|
	{
 | 
						|
	case ConVarBound_Upper:
 | 
						|
		pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
 | 
						|
		break;
 | 
						|
	case ConVarBound_Lower:
 | 
						|
		pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[1]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static bool s_QueryAlreadyWarned = false;
 | 
						|
 | 
						|
static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	CPlayer *pPlayer;
 | 
						|
	char *name;
 | 
						|
	IPluginFunction *pCallback;
 | 
						|
 | 
						|
	if (!g_ConVarManager.IsQueryingSupported())
 | 
						|
	{
 | 
						|
		if (!s_QueryAlreadyWarned)
 | 
						|
		{
 | 
						|
			s_QueryAlreadyWarned = true;
 | 
						|
			return pContext->ThrowNativeError("Game does not support client convar querying (one time warning)");
 | 
						|
		}
 | 
						|
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Trying a query on a bot results in callback not be fired, so don't bother */
 | 
						|
	if (pPlayer->IsFakeClient())
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->LocalToString(params[2], &name);
 | 
						|
	pCallback = pContext->GetFunctionById(params[3]);
 | 
						|
 | 
						|
	if (!pCallback)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
 | 
						|
	}
 | 
						|
 | 
						|
	return g_ConVarManager.QueryClientConVar(pPlayer->GetEdict(), name, pCallback, params[4]);
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name,*help;
 | 
						|
	IPluginFunction *pFunction;
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	if (strcasecmp(name, "sm") == 0)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Cannot register \"sm\" command");
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->LocalToString(params[3], &help);
 | 
						|
	pFunction = pContext->GetFunctionById(params[2]);
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name,*help;
 | 
						|
	IPluginFunction *pFunction;
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	if (strcasecmp(name, "sm") == 0)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Cannot register \"sm\" command");
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->LocalToString(params[3], &help);
 | 
						|
	pFunction = pContext->GetFunctionById(params[2]);
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
 | 
						|
	}
 | 
						|
 | 
						|
	IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
 | 
						|
	const char *group = pPlugin->GetFilename();
 | 
						|
	if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4]))
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name,*help;
 | 
						|
	const char *group;
 | 
						|
	IPluginFunction *pFunction;
 | 
						|
	FlagBits flags = params[3];
 | 
						|
	int cmdflags = params[6];
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	if (strcasecmp(name, "sm") == 0)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Cannot register \"sm\" command");
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->LocalToString(params[4], &help);
 | 
						|
	pContext->LocalToString(params[5], (char **)&group);
 | 
						|
	pFunction = pContext->GetFunctionById(params[2]);
 | 
						|
 | 
						|
	if (group[0] == '\0')
 | 
						|
	{
 | 
						|
		IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
 | 
						|
		group = pPlugin->GetFilename();
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	const CCommand *pCmd = g_HL2.PeekCommandStack();
 | 
						|
 | 
						|
	if (!pCmd)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("No command callback available");
 | 
						|
	}
 | 
						|
 | 
						|
	return pCmd->ArgC() - 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	const CCommand *pCmd = g_HL2.PeekCommandStack();
 | 
						|
 | 
						|
	if (!pCmd)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("No command callback available");
 | 
						|
	}
 | 
						|
 | 
						|
	size_t length;
 | 
						|
 | 
						|
	const char *arg = pCmd->Arg(params[1]);
 | 
						|
	
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], arg ? arg : "", &length);
 | 
						|
 | 
						|
	return (cell_t)length;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	const CCommand *pCmd = g_HL2.PeekCommandStack();
 | 
						|
 | 
						|
	if (!pCmd)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("No command callback available");
 | 
						|
	}
 | 
						|
 | 
						|
	const char *args = pCmd->ArgS();
 | 
						|
	size_t length;
 | 
						|
 | 
						|
	if (!args)
 | 
						|
	{
 | 
						|
		args = "";
 | 
						|
	}
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[1], params[2], args, &length);
 | 
						|
 | 
						|
	return (cell_t)length;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
 | 
						|
{
 | 
						|
	char buffer[1024];
 | 
						|
	char *fmt;
 | 
						|
	int arg = 2;
 | 
						|
 | 
						|
	pCtx->LocalToString(params[1], &fmt);
 | 
						|
	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
 | 
						|
 | 
						|
	buffer[res++] = '\n';
 | 
						|
	buffer[res] = '\0';
 | 
						|
 | 
						|
	META_CONPRINT(buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
 | 
						|
{
 | 
						|
	int index = params[1];
 | 
						|
	if ((index < 0) || (index > g_Players.GetMaxClients()))
 | 
						|
	{
 | 
						|
		return pCtx->ThrowNativeError("Client index %d is invalid", index);
 | 
						|
	}
 | 
						|
 | 
						|
	CPlayer *pPlayer = NULL;
 | 
						|
	if (index != 0)
 | 
						|
	{
 | 
						|
		pPlayer = g_Players.GetPlayerByIndex(index);
 | 
						|
		if (!pPlayer->IsInGame())
 | 
						|
		{
 | 
						|
			return pCtx->ThrowNativeError("Client %d is not in game", index);
 | 
						|
		}
 | 
						|
		
 | 
						|
		/* Silent fail on bots, engine will crash */
 | 
						|
		if (pPlayer->IsFakeClient())
 | 
						|
		{
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	char buffer[1024];
 | 
						|
	char *fmt;
 | 
						|
	int arg = 3;
 | 
						|
 | 
						|
	pCtx->LocalToString(params[2], &fmt);
 | 
						|
	size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
 | 
						|
 | 
						|
	buffer[res++] = '\n';
 | 
						|
	buffer[res] = '\0';
 | 
						|
 | 
						|
	if (index != 0)
 | 
						|
	{
 | 
						|
#if SOURCE_ENGINE == SE_DOTA
 | 
						|
		engine->ClientPrintf(pPlayer->GetIndex(), buffer);
 | 
						|
#else
 | 
						|
		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
 | 
						|
#endif
 | 
						|
	} else {
 | 
						|
		META_CONPRINT(buffer);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
 | 
						|
 | 
						|
	char buffer[1024];
 | 
						|
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* One byte for null terminator, one for newline */
 | 
						|
	buffer[len++] = '\n';
 | 
						|
	buffer[len] = '\0';
 | 
						|
 | 
						|
	engine->ServerCommand(buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
char *g_ServerCommandBuffer = NULL;
 | 
						|
cell_t g_ServerCommandBufferLength;
 | 
						|
 | 
						|
bool g_ShouldCatchSpew = false;
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_NUCLEARDAWN
 | 
						|
SpewOutputFunc_t g_OriginalSpewOutputFunc = NULL;
 | 
						|
 | 
						|
SpewRetval_t SourcemodSpewOutputFunc(SpewType_t spewType, tchar const *pMsg)
 | 
						|
{
 | 
						|
	if (g_ServerCommandBuffer)
 | 
						|
	{
 | 
						|
		V_strcat(g_ServerCommandBuffer, pMsg, g_ServerCommandBufferLength);
 | 
						|
	}
 | 
						|
 | 
						|
	if (g_OriginalSpewOutputFunc)
 | 
						|
	{
 | 
						|
		return g_OriginalSpewOutputFunc(spewType, pMsg);
 | 
						|
	} else {
 | 
						|
		return SPEW_CONTINUE;
 | 
						|
	}
 | 
						|
}
 | 
						|
#else
 | 
						|
class CSourcemodLoggingListener: public ILoggingListener
 | 
						|
{
 | 
						|
public:
 | 
						|
	void Log(const LoggingContext_t *pContext, const tchar *pMessage)
 | 
						|
	{
 | 
						|
		if (g_ServerCommandBuffer)
 | 
						|
		{
 | 
						|
			V_strcat(g_ServerCommandBuffer, pMessage, g_ServerCommandBufferLength);
 | 
						|
		}
 | 
						|
	}
 | 
						|
} g_SourcemodLoggingListener;
 | 
						|
#endif
 | 
						|
 | 
						|
CON_COMMAND(sm_conhook_start, "")
 | 
						|
{
 | 
						|
	if (!g_ShouldCatchSpew)
 | 
						|
	{
 | 
						|
		Warning("You shouldn't run this command!\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_NUCLEARDAWN
 | 
						|
	g_OriginalSpewOutputFunc = GetSpewOutputFunc();
 | 
						|
	SpewOutputFunc(SourcemodSpewOutputFunc);
 | 
						|
#else
 | 
						|
#if SOURCE_ENGINE < SE_ALIENSWARM
 | 
						|
	LoggingSystem_PushLoggingState(false);
 | 
						|
#else
 | 
						|
	LoggingSystem_PushLoggingState(false, false);
 | 
						|
#endif
 | 
						|
	LoggingSystem_RegisterLoggingListener(&g_SourcemodLoggingListener);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
CON_COMMAND(sm_conhook_stop, "")
 | 
						|
{
 | 
						|
	if (!g_ShouldCatchSpew)
 | 
						|
	{
 | 
						|
		Warning("You shouldn't run this command!\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
#if SOURCE_ENGINE < SE_NUCLEARDAWN
 | 
						|
	SpewOutputFunc(g_OriginalSpewOutputFunc);
 | 
						|
#else
 | 
						|
	LoggingSystem_PopLoggingState(false);
 | 
						|
#endif
 | 
						|
 | 
						|
	g_ShouldCatchSpew = false;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_ServerCommandEx(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
 | 
						|
 | 
						|
	char buffer[1024];
 | 
						|
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 3);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* One byte for null terminator, one for newline */
 | 
						|
	buffer[len++] = '\n';
 | 
						|
	buffer[len] = '\0';
 | 
						|
 | 
						|
	pContext->LocalToString(params[1], &g_ServerCommandBuffer);
 | 
						|
	g_ServerCommandBufferLength = params[2];
 | 
						|
	
 | 
						|
	if (g_ServerCommandBufferLength > 0)
 | 
						|
	{
 | 
						|
		g_ServerCommandBuffer[0] = '\0';
 | 
						|
	}
 | 
						|
 | 
						|
	engine->ServerExecute();
 | 
						|
 | 
						|
	g_ShouldCatchSpew = true;
 | 
						|
	engine->ServerCommand("sm_conhook_start\n");
 | 
						|
	engine->ServerCommand(buffer);
 | 
						|
	engine->ServerCommand("sm_conhook_stop\n");
 | 
						|
 | 
						|
	engine->ServerExecute();
 | 
						|
 | 
						|
	if (g_ServerCommandBufferLength > 0)
 | 
						|
	{
 | 
						|
		g_ServerCommandBuffer[g_ServerCommandBufferLength-1] = '\0';
 | 
						|
	}
 | 
						|
 | 
						|
	g_ServerCommandBuffer = NULL;
 | 
						|
	g_ServerCommandBufferLength = 0;
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
 | 
						|
 | 
						|
	char buffer[1024];
 | 
						|
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* One byte for null terminator, one for newline */
 | 
						|
	buffer[len++] = '\n';
 | 
						|
	buffer[len] = '\0';
 | 
						|
 | 
						|
	InsertServerCommand(buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	engine->ServerExecute();
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	g_SourceMod.SetGlobalTarget(params[1]);
 | 
						|
 | 
						|
	char buffer[256];
 | 
						|
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	engine->ClientCommand(
 | 
						|
#if SOURCE_ENGINE == SE_DOTA
 | 
						|
		pPlayer->GetIndex(),
 | 
						|
#else
 | 
						|
		pPlayer->GetEdict(),
 | 
						|
#endif
 | 
						|
		"%s", buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	g_SourceMod.SetGlobalTarget(params[1]);
 | 
						|
 | 
						|
	char buffer[256];
 | 
						|
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
#if SOURCE_ENGINE == SE_DOTA
 | 
						|
	engine->ClientCommand(pPlayer->GetIndex(), "%s", buffer);
 | 
						|
#else
 | 
						|
	serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
 | 
						|
#endif
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	g_SourceMod.SetGlobalTarget(params[1]);
 | 
						|
 | 
						|
	char buffer[256];
 | 
						|
	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	g_HL2.AddToFakeCliCmdQueue(params[1], GetPlayerUserId(pPlayer->GetEdict()), buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	g_SourceMod.SetGlobalTarget(params[1]);
 | 
						|
 | 
						|
	/* Build the format string */
 | 
						|
	char buffer[1024];
 | 
						|
	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
 | 
						|
 | 
						|
	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* If we're printing to the server, shortcut out */
 | 
						|
	if (params[1] == 0)
 | 
						|
	{
 | 
						|
		/* Print */
 | 
						|
		buffer[len++] = '\n';
 | 
						|
		buffer[len] = '\0';
 | 
						|
		META_CONPRINT(buffer);
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	unsigned int replyto = g_ChatTriggers.GetReplyTo();
 | 
						|
	if (replyto == SM_REPLY_CONSOLE)
 | 
						|
	{
 | 
						|
		buffer[len++] = '\n';
 | 
						|
		buffer[len] = '\0';
 | 
						|
#if SOURCE_ENGINE == SE_DOTA
 | 
						|
		engine->ClientPrintf(pPlayer->GetIndex(), buffer);
 | 
						|
#else
 | 
						|
		engine->ClientPrintf(pPlayer->GetEdict(), buffer);
 | 
						|
#endif
 | 
						|
	} else if (replyto == SM_REPLY_CHAT) {
 | 
						|
		if (len >= 191)
 | 
						|
		{
 | 
						|
			len = 191;
 | 
						|
		}
 | 
						|
		buffer[len] = '\0';
 | 
						|
		g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	return g_ChatTriggers.GetReplyTo();
 | 
						|
}
 | 
						|
 | 
						|
static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	return g_ChatTriggers.SetReplyTo(params[1]);
 | 
						|
}
 | 
						|
 | 
						|
static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	GlobCmdIter *iter = new GlobCmdIter;
 | 
						|
	iter->started = false;
 | 
						|
 | 
						|
	Handle_t hndl = handlesys->CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
 | 
						|
	if (hndl == BAD_HANDLE)
 | 
						|
	{
 | 
						|
		delete iter;
 | 
						|
	}
 | 
						|
 | 
						|
	return hndl;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	GlobCmdIter *iter;
 | 
						|
	HandleError err;
 | 
						|
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
 | 
						|
 | 
						|
	if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
 | 
						|
 | 
						|
	if (!iter->started)
 | 
						|
	{
 | 
						|
		iter->iter = cmds.begin();
 | 
						|
		iter->started = true;
 | 
						|
	}
 | 
						|
 | 
						|
	while (iter->iter != cmds.end()
 | 
						|
			&& !(*(iter->iter))->sourceMod)
 | 
						|
	{
 | 
						|
		iter->iter++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (iter->iter == cmds.end())
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	ConCmdInfo *pInfo = (*(iter->iter));
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
 | 
						|
	pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL);
 | 
						|
	
 | 
						|
	cell_t *addr;
 | 
						|
	pContext->LocalToPhysAddr(params[4], &addr);
 | 
						|
	*addr = pInfo->eflags;
 | 
						|
 | 
						|
	iter->iter++;
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	if (params[1] == 0)
 | 
						|
	{
 | 
						|
		return 1;
 | 
						|
	}
 | 
						|
 | 
						|
	char *cmd;
 | 
						|
	pContext->LocalToString(params[2], &cmd);
 | 
						|
 | 
						|
	/* Match up with an admin command if possible */
 | 
						|
	FlagBits bits = params[3];
 | 
						|
	bool found_command = false;
 | 
						|
	if (params[0] < 4 || !params[4])
 | 
						|
	{
 | 
						|
		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
 | 
						|
	}
 | 
						|
	
 | 
						|
	if (!found_command)
 | 
						|
	{
 | 
						|
		g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
 | 
						|
	}
 | 
						|
 | 
						|
	return g_ConCmds.CheckClientCommandAccess(params[1], cmd, bits) ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t CheckAccess(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *cmd;
 | 
						|
	pContext->LocalToString(params[2], &cmd);
 | 
						|
 | 
						|
	/* Match up with an admin command if possible */
 | 
						|
	FlagBits bits = params[3];
 | 
						|
	bool found_command = false;
 | 
						|
	if (params[0] < 4 || !params[4])
 | 
						|
	{
 | 
						|
		found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
 | 
						|
	}
 | 
						|
	
 | 
						|
	if (!found_command)
 | 
						|
	{
 | 
						|
		g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
 | 
						|
	}
 | 
						|
 | 
						|
	return g_ConCmds.CheckAdminCommandAccess(params[1], cmd, bits) ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t IsChatTrigger(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	return g_ChatTriggers.IsChatTrigger() ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t SetCommandFlags(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	return (s_CommandFlagsHelper.SetFlags(name, params[2])) ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t GetCommandFlags(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
	int flags;
 | 
						|
	pContext->LocalToString(params[1], &name);
 | 
						|
 | 
						|
	return (s_CommandFlagsHelper.GetFlags(name, &flags)) ? flags : -1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl;
 | 
						|
	ConCommandBaseIterator *pIter;
 | 
						|
	cell_t *pIsCmd, *pFlags;
 | 
						|
	const ConCommandBase *pConCmd;
 | 
						|
	const char *desc;
 | 
						|
 | 
						|
	pContext->LocalToPhysAddr(params[3], &pIsCmd);
 | 
						|
	pContext->LocalToPhysAddr(params[4], &pFlags);
 | 
						|
 | 
						|
	pIter = new ConCommandBaseIterator();
 | 
						|
 | 
						|
	if (!pIter->IsValid())
 | 
						|
	{
 | 
						|
		delete pIter;
 | 
						|
		return BAD_HANDLE;
 | 
						|
	}
 | 
						|
 | 
						|
	pConCmd = pIter->Get();
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL);
 | 
						|
	*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
 | 
						|
	*pFlags = pConCmd->GetFlags();
 | 
						|
 | 
						|
	if (params[6])
 | 
						|
	{
 | 
						|
		desc = pConCmd->GetHelpText();
 | 
						|
		pContext->StringToLocalUTF8(params[5], params[6], (desc && desc[0]) ? desc : "", NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	if ((hndl = handlesys->CreateHandle(htConCmdIter, pIter, pContext->GetIdentity(), g_pCoreIdent, NULL))
 | 
						|
		== BAD_HANDLE)
 | 
						|
	{
 | 
						|
		delete pIter;
 | 
						|
		return BAD_HANDLE;
 | 
						|
	}
 | 
						|
 | 
						|
	return hndl;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	HandleError err;
 | 
						|
	ConCommandBaseIterator *pIter;
 | 
						|
	cell_t *pIsCmd, *pFlags;
 | 
						|
	const char *desc;
 | 
						|
	const ConCommandBase *pConCmd;
 | 
						|
	HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
 | 
						|
 | 
						|
	if ((err = handlesys->ReadHandle(params[1], htConCmdIter, &sec, (void **)&pIter)) != HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pIter->IsValid())
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	pIter->Next();
 | 
						|
	if (!pIter->IsValid())
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	pConCmd = pIter->Get();
 | 
						|
 | 
						|
	pContext->LocalToPhysAddr(params[4], &pIsCmd);
 | 
						|
	pContext->LocalToPhysAddr(params[5], &pFlags);
 | 
						|
 | 
						|
	pContext->StringToLocalUTF8(params[2], params[3], pConCmd->GetName(), NULL);
 | 
						|
	*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
 | 
						|
	*pFlags = pConCmd->GetFlags();
 | 
						|
 | 
						|
	if (params[7])
 | 
						|
	{
 | 
						|
		desc = pConCmd->GetHelpText();
 | 
						|
		pContext->StringToLocalUTF8(params[6], params[7], (desc && desc[0]) ? desc : "", NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	Handle_t hndl = static_cast<Handle_t>(params[2]);
 | 
						|
	HandleError err;
 | 
						|
	ConVar *pConVar;
 | 
						|
 | 
						|
	char *value;
 | 
						|
	pContext->LocalToString(params[3], &value);
 | 
						|
 | 
						|
	if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
 | 
						|
		!= HandleError_None)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
 | 
						|
	}
 | 
						|
 | 
						|
	char data[256];
 | 
						|
	bf_write buffer(data, sizeof(data));
 | 
						|
 | 
						|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
 | 
						|
	CNETMsg_SetConVar msg;
 | 
						|
	CMsg_CVars_CVar *cvar = msg.mutable_convars()->add_cvars();
 | 
						|
 | 
						|
	cvar->set_name(pConVar->GetName());
 | 
						|
	cvar->set_value(value);
 | 
						|
 | 
						|
	int msgsize = msg.ByteSize();
 | 
						|
   
 | 
						|
	buffer.WriteVarInt32(net_SetConVar);
 | 
						|
	buffer.WriteVarInt32(msgsize);
 | 
						|
	msg.SerializeWithCachedSizesToArray( (uint8 *)( buffer.GetBasePointer() + buffer.GetNumBytesWritten() ) );
 | 
						|
	buffer.SeekToBit( ( buffer.GetNumBytesWritten() + msgsize ) * 8 );
 | 
						|
#else
 | 
						|
	buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
 | 
						|
	buffer.WriteByte(1);
 | 
						|
	buffer.WriteString(pConVar->GetName());
 | 
						|
	buffer.WriteString(value);
 | 
						|
#endif
 | 
						|
 | 
						|
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
 | 
						|
 | 
						|
	if (!pPlayer)
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!pPlayer->IsConnected())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	if (pPlayer->IsFakeClient())
 | 
						|
	{
 | 
						|
		return pContext->ThrowNativeError("Client %d is fake and cannot be targeted", params[1]);
 | 
						|
	}
 | 
						|
 | 
						|
	INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
 | 
						|
	if (netchan == NULL)
 | 
						|
	{
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	netchan->SendData(buffer);
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t AddServerTag(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t RemoveServerTag(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t AddCommandListener(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
	IPluginFunction *pFunction;
 | 
						|
 | 
						|
	pContext->LocalToString(params[2], &name);
 | 
						|
 | 
						|
	if (strcasecmp(name, "sm") == 0)
 | 
						|
	{
 | 
						|
		g_Logger.LogError("Request to register \"sm\" command denied.");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	pFunction = pContext->GetFunctionById(params[1]);
 | 
						|
 | 
						|
	if (!pFunction)
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
 | 
						|
 | 
						|
	if (!g_ConsoleDetours.AddListener(pFunction, name[0] == '\0' ? NULL : name))
 | 
						|
		return pContext->ThrowNativeError("This game does not support command listeners");
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static cell_t RemoveCommandListener(IPluginContext *pContext, const cell_t *params)
 | 
						|
{
 | 
						|
	char *name;
 | 
						|
	IPluginFunction *pFunction;
 | 
						|
 | 
						|
	pContext->LocalToString(params[2], &name);
 | 
						|
	pFunction = pContext->GetFunctionById(params[1]);
 | 
						|
	if (!pFunction)
 | 
						|
		return pContext->ThrowNativeError("Invalid function id (%X)", params[1]);
 | 
						|
 | 
						|
	if (!g_ConsoleDetours.RemoveListener(pFunction, name[0] == '\0' ? NULL : name))
 | 
						|
		return pContext->ThrowNativeError("No matching callback was registered");
 | 
						|
	
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
REGISTER_NATIVES(consoleNatives)
 | 
						|
{
 | 
						|
	{"CreateConVar",		sm_CreateConVar},
 | 
						|
	{"FindConVar",			sm_FindConVar},
 | 
						|
	{"HookConVarChange",	sm_HookConVarChange},
 | 
						|
	{"UnhookConVarChange",	sm_UnhookConVarChange},
 | 
						|
	{"GetConVarBool",		sm_GetConVarBool},
 | 
						|
	{"SetConVarBool",		sm_SetConVarNum},
 | 
						|
	{"GetConVarInt",		sm_GetConVarInt},
 | 
						|
	{"SetConVarInt",		sm_SetConVarNum},
 | 
						|
	{"GetConVarFloat",		sm_GetConVarFloat},
 | 
						|
	{"SetConVarFloat",		sm_SetConVarFloat},
 | 
						|
	{"GetConVarString",		sm_GetConVarString},
 | 
						|
	{"SetConVarString",		sm_SetConVarString},
 | 
						|
	{"GetConVarFlags",		sm_GetConVarFlags},
 | 
						|
	{"SetConVarFlags",		sm_SetConVarFlags},
 | 
						|
	{"ResetConVar",			sm_ResetConVar},
 | 
						|
	{"GetConVarName",		sm_GetConVarName},
 | 
						|
	{"GetConVarBounds",		sm_GetConVarBounds},
 | 
						|
	{"SetConVarBounds",		sm_SetConVarBounds},
 | 
						|
	{"QueryClientConVar",	sm_QueryClientConVar},
 | 
						|
	{"GetConVarDefault",	GetConVarDefault},
 | 
						|
	{"RegServerCmd",		sm_RegServerCmd},
 | 
						|
	{"RegConsoleCmd",		sm_RegConsoleCmd},
 | 
						|
	{"GetCmdArgString",		sm_GetCmdArgString},
 | 
						|
	{"GetCmdArgs",			sm_GetCmdArgs},
 | 
						|
	{"GetCmdArg",			sm_GetCmdArg},
 | 
						|
	{"PrintToServer",		sm_PrintToServer},
 | 
						|
	{"PrintToConsole",		sm_PrintToConsole},
 | 
						|
	{"RegAdminCmd",			sm_RegAdminCmd},
 | 
						|
	{"ServerCommand",		sm_ServerCommand},
 | 
						|
	{"ServerCommandEx",		sm_ServerCommandEx},
 | 
						|
	{"InsertServerCommand",	sm_InsertServerCommand},
 | 
						|
	{"ServerExecute",		sm_ServerExecute},
 | 
						|
	{"ClientCommand",		sm_ClientCommand},
 | 
						|
	{"FakeClientCommand",	FakeClientCommand},
 | 
						|
	{"ReplyToCommand",		ReplyToCommand},
 | 
						|
	{"GetCmdReplySource",	GetCmdReplyTarget},
 | 
						|
	{"SetCmdReplySource",	SetCmdReplyTarget},
 | 
						|
	{"GetCommandIterator",	GetCommandIterator},
 | 
						|
	{"ReadCommandIterator",	ReadCommandIterator},
 | 
						|
	{"CheckCommandAccess",	CheckCommandAccess},
 | 
						|
	{"CheckAccess",			CheckAccess},
 | 
						|
	{"FakeClientCommandEx",	FakeClientCommandEx},
 | 
						|
	{"IsChatTrigger",		IsChatTrigger},
 | 
						|
	{"SetCommandFlags",		SetCommandFlags},
 | 
						|
	{"GetCommandFlags",		GetCommandFlags},
 | 
						|
	{"FindFirstConCommand",	FindFirstConCommand},
 | 
						|
	{"FindNextConCommand",	FindNextConCommand},
 | 
						|
	{"SendConVarValue",		SendConVarValue},
 | 
						|
	{"AddServerTag",		AddServerTag},
 | 
						|
	{"RemoveServerTag",		RemoveServerTag},
 | 
						|
	{"AddCommandListener",	AddCommandListener},
 | 
						|
	{"RemoveCommandListener", RemoveCommandListener},
 | 
						|
	{NULL,					NULL}
 | 
						|
};
 |