2008-03-30 09:00:22 +02:00
|
|
|
/**
|
|
|
|
* vim: set ts=4 :
|
|
|
|
* =============================================================================
|
|
|
|
* SourceMod
|
2010-05-05 04:53:26 +02:00
|
|
|
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
2008-03-30 09:00:22 +02:00
|
|
|
* =============================================================================
|
|
|
|
*
|
|
|
|
* 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 "HalfLife2.h"
|
|
|
|
#include "sourcemm_api.h"
|
|
|
|
#include "HandleSys.h"
|
|
|
|
#include "ConVarManager.h"
|
|
|
|
#include "ConCmdManager.h"
|
|
|
|
#include "PluginSys.h"
|
|
|
|
#include "sm_stringutil.h"
|
|
|
|
#include "PlayerManager.h"
|
|
|
|
#include "ChatTriggers.h"
|
|
|
|
#include "AdminCache.h"
|
|
|
|
#include <inetchannel.h>
|
|
|
|
#include <bitbuf.h>
|
|
|
|
#include <sm_trie_tpl.h>
|
2011-07-18 04:23:03 +02:00
|
|
|
#include <tier0/dbg.h>
|
2009-09-26 23:12:23 +02:00
|
|
|
#include "Logger.h"
|
|
|
|
#include "ConsoleDetours.h"
|
2010-07-28 00:32:32 +02:00
|
|
|
#include "ConCommandBaseIterator.h"
|
2008-03-30 09:00:22 +02:00
|
|
|
|
2013-01-23 03:43:12 +01:00
|
|
|
#if SOURCE_ENGINE == SE_CSGO
|
|
|
|
#include <netmessages.pb.h>
|
|
|
|
#endif
|
|
|
|
|
2011-08-21 00:58:37 +02:00
|
|
|
#if SOURCE_ENGINE >= SE_EYE
|
2010-05-05 04:53:26 +02:00
|
|
|
#define NETMSG_BITS 6
|
|
|
|
#else
|
|
|
|
#define NETMSG_BITS 5
|
|
|
|
#endif
|
|
|
|
|
2010-07-28 00:32:32 +02:00
|
|
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
2008-11-14 16:18:30 +01:00
|
|
|
#define NET_SETCONVAR 6
|
|
|
|
#else
|
2008-03-30 09:00:22 +02:00
|
|
|
#define NET_SETCONVAR 5
|
2008-11-14 16:18:30 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
g_HandleSys.InitAccessDefaults(NULL, &access);
|
|
|
|
|
|
|
|
htConCmdIter = g_HandleSys.CreateType("ConCmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
|
|
|
|
|
|
|
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
|
|
|
|
|
|
|
|
hCmdIterType = g_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)
|
|
|
|
{
|
2010-07-28 00:32:32 +02:00
|
|
|
ConCommandBaseIterator *iter = (ConCommandBaseIterator * )object;
|
2008-03-30 09:00:22 +02:00
|
|
|
delete iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
|
|
|
|
{
|
|
|
|
if (type == htConCmdIter)
|
|
|
|
{
|
2010-07-28 00:32:32 +02:00
|
|
|
*pSize = sizeof(ConCommandBaseIterator);
|
2008-03-30 09:00:22 +02:00
|
|
|
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 **ppCmd;
|
|
|
|
ConCommandBase *pCmd;
|
|
|
|
if ((ppCmd=m_CmdFlags.retrieve(name)))
|
|
|
|
{
|
|
|
|
TrackConCommandBase((*ppCmd), this);
|
|
|
|
*flags = (*ppCmd)->GetFlags();
|
|
|
|
return true;
|
|
|
|
}
|
2008-11-14 16:18:30 +01:00
|
|
|
else if ((pCmd=FindCommandBase(name)))
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
m_CmdFlags.insert(name, pCmd);
|
|
|
|
TrackConCommandBase(pCmd, this);
|
|
|
|
*flags = pCmd->GetFlags();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool SetFlags(const char *name, int flags)
|
|
|
|
{
|
|
|
|
ConCommandBase **ppCmd;
|
|
|
|
ConCommandBase *pCmd;
|
|
|
|
if ((ppCmd=m_CmdFlags.retrieve(name)))
|
|
|
|
{
|
|
|
|
(*ppCmd)->SetFlags(flags);
|
|
|
|
TrackConCommandBase((*ppCmd), this);
|
|
|
|
return true;
|
|
|
|
}
|
2008-11-14 16:18:30 +01:00
|
|
|
else if ((pCmd=FindCommandBase(name)))
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
m_CmdFlags.insert(name, pCmd);
|
|
|
|
pCmd->SetFlags(flags);
|
|
|
|
TrackConCommandBase(pCmd, this);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
KTrie<ConCommandBase *> m_CmdFlags;
|
|
|
|
} s_CommandFlagsHelper;
|
|
|
|
|
2010-07-15 03:29:45 +02:00
|
|
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
2008-03-30 09:00:22 +02:00
|
|
|
static void ReplicateConVar(ConVar *pConVar)
|
|
|
|
{
|
|
|
|
int maxClients = g_Players.GetMaxClients();
|
|
|
|
|
|
|
|
char data[256];
|
|
|
|
bf_write buffer(data, sizeof(data));
|
|
|
|
|
2010-05-05 04:53:26 +02:00
|
|
|
buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
|
2008-03-30 09:00:22 +02:00
|
|
|
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())
|
|
|
|
{
|
2010-04-28 08:40:04 +02:00
|
|
|
if (INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i)))
|
|
|
|
netchan->SendData(buffer);
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2008-11-13 06:22:33 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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]);
|
|
|
|
|
2010-07-15 03:29:45 +02:00
|
|
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
2008-03-30 09:00:22 +02:00
|
|
|
/* 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);
|
|
|
|
}
|
2008-11-13 06:14:49 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2010-07-15 03:29:45 +02:00
|
|
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
2008-03-30 09:00:22 +02:00
|
|
|
/* 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);
|
|
|
|
}
|
2008-11-13 06:14:49 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2010-07-15 03:29:45 +02:00
|
|
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
2008-03-30 09:00:22 +02:00
|
|
|
/* 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);
|
|
|
|
}
|
2008-11-13 06:14:49 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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();
|
|
|
|
|
2010-07-15 03:29:45 +02:00
|
|
|
#if SOURCE_ENGINE < SE_ORANGEBOX
|
2008-03-30 09:00:22 +02:00
|
|
|
/* Should we replicate it? */
|
2008-11-13 06:14:49 +01:00
|
|
|
if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
ReplicateConVar(pConVar);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Should we notify clients? */
|
2008-11-13 06:14:49 +01:00
|
|
|
if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
NotifyConVar(pConVar);
|
|
|
|
}
|
2008-11-13 06:14:49 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-07-07 00:32:58 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
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);
|
2009-09-17 07:37:20 +02:00
|
|
|
|
|
|
|
if (strcasecmp(name, "sm") == 0)
|
|
|
|
{
|
2009-09-26 23:12:23 +02:00
|
|
|
return pContext->ThrowNativeError("Cannot register \"sm\" command");
|
2009-09-17 07:37:20 +02:00
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
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);
|
2009-09-17 07:37:20 +02:00
|
|
|
|
|
|
|
if (strcasecmp(name, "sm") == 0)
|
|
|
|
{
|
2009-09-26 23:12:23 +02:00
|
|
|
return pContext->ThrowNativeError("Cannot register \"sm\" command");
|
2009-09-17 07:37:20 +02:00
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
pContext->LocalToString(params[3], &help);
|
|
|
|
pFunction = pContext->GetFunctionById(params[2]);
|
|
|
|
|
|
|
|
if (!pFunction)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
|
|
|
|
}
|
|
|
|
|
2012-11-15 18:53:11 +01:00
|
|
|
CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
|
|
|
|
const char *group = pPlugin->GetFilename();
|
|
|
|
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4]))
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
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);
|
2009-09-17 07:37:20 +02:00
|
|
|
|
|
|
|
if (strcasecmp(name, "sm") == 0)
|
|
|
|
{
|
2009-09-26 23:12:23 +02:00
|
|
|
return pContext->ThrowNativeError("Cannot register \"sm\" command");
|
2009-09-17 07:37:20 +02:00
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
pContext->LocalToString(params[4], &help);
|
|
|
|
pContext->LocalToString(params[5], (char **)&group);
|
|
|
|
pFunction = pContext->GetFunctionById(params[2]);
|
|
|
|
|
|
|
|
if (group[0] == '\0')
|
|
|
|
{
|
|
|
|
CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(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)
|
|
|
|
{
|
|
|
|
engine->ClientPrintf(pPlayer->GetEdict(), buffer);
|
|
|
|
} else {
|
|
|
|
META_CONPRINT(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
2008-05-10 11:23:55 +02:00
|
|
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
char buffer[1024];
|
|
|
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One byte for null terminator, one for newline */
|
|
|
|
buffer[len++] = '\n';
|
|
|
|
buffer[len] = '\0';
|
|
|
|
|
|
|
|
engine->ServerCommand(buffer);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-07-18 04:23:03 +02:00
|
|
|
char *g_ServerCommandBuffer = NULL;
|
|
|
|
cell_t g_ServerCommandBufferLength;
|
|
|
|
|
|
|
|
bool g_ShouldCatchSpew = false;
|
|
|
|
|
|
|
|
#if SOURCE_ENGINE < SE_LEFT4DEAD2
|
|
|
|
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_LEFT4DEAD2
|
|
|
|
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_LEFT4DEAD2
|
|
|
|
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];
|
2011-10-17 17:02:42 +02:00
|
|
|
|
|
|
|
if (g_ServerCommandBufferLength > 0)
|
|
|
|
{
|
|
|
|
g_ServerCommandBuffer[0] = '\0';
|
|
|
|
}
|
2011-07-18 04:23:03 +02:00
|
|
|
|
|
|
|
engine->ServerExecute();
|
|
|
|
|
|
|
|
g_ShouldCatchSpew = true;
|
|
|
|
engine->ServerCommand("sm_conhook_start\n");
|
|
|
|
engine->ServerCommand(buffer);
|
|
|
|
engine->ServerCommand("sm_conhook_stop\n");
|
|
|
|
|
|
|
|
engine->ServerExecute();
|
|
|
|
|
2011-10-17 17:02:42 +02:00
|
|
|
if (g_ServerCommandBufferLength > 0)
|
|
|
|
{
|
|
|
|
g_ServerCommandBuffer[g_ServerCommandBufferLength-1] = '\0';
|
|
|
|
}
|
2011-07-18 04:23:03 +02:00
|
|
|
|
|
|
|
g_ServerCommandBuffer = NULL;
|
|
|
|
g_ServerCommandBufferLength = 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
2008-05-10 11:23:55 +02:00
|
|
|
g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
char buffer[1024];
|
|
|
|
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
engine->ClientCommand(pPlayer->GetEdict(), "%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]);
|
|
|
|
}
|
|
|
|
|
|
|
|
char buffer[256];
|
|
|
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
|
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
|
|
|
char buffer[256];
|
|
|
|
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_HL2.AddToFakeCliCmdQueue(params[1], engine->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);
|
|
|
|
|
2008-07-11 10:18:43 +02:00
|
|
|
if (pContext->GetLastNativeError() != SP_ERROR_NONE)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_SourceMod.SetGlobalTarget(params[1]);
|
|
|
|
|
|
|
|
unsigned int replyto = g_ChatTriggers.GetReplyTo();
|
|
|
|
if (replyto == SM_REPLY_CONSOLE)
|
|
|
|
{
|
|
|
|
buffer[len++] = '\n';
|
|
|
|
buffer[len] = '\0';
|
|
|
|
engine->ClientPrintf(pPlayer->GetEdict(), buffer);
|
|
|
|
} 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 = g_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 = g_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->admin.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);
|
|
|
|
|
2011-09-10 18:08:38 +02:00
|
|
|
/* Match up with an admin command if possible */
|
2008-03-30 09:00:22 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-09-10 18:08:38 +02:00
|
|
|
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;
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2010-07-28 00:32:32 +02:00
|
|
|
ConCommandBaseIterator *pIter;
|
2008-03-30 09:00:22 +02:00
|
|
|
cell_t *pIsCmd, *pFlags;
|
|
|
|
const ConCommandBase *pConCmd;
|
|
|
|
const char *desc;
|
|
|
|
|
|
|
|
pContext->LocalToPhysAddr(params[3], &pIsCmd);
|
|
|
|
pContext->LocalToPhysAddr(params[4], &pFlags);
|
|
|
|
|
2010-07-28 00:32:32 +02:00
|
|
|
pIter = new ConCommandBaseIterator();
|
|
|
|
|
|
|
|
if (!pIter->IsValid())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2010-07-28 00:32:32 +02:00
|
|
|
delete pIter;
|
2008-03-30 09:00:22 +02:00
|
|
|
return BAD_HANDLE;
|
|
|
|
}
|
2010-07-28 00:32:32 +02:00
|
|
|
|
|
|
|
pConCmd = pIter->Get();
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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 = g_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;
|
2010-07-28 00:32:32 +02:00
|
|
|
ConCommandBaseIterator *pIter;
|
2008-03-30 09:00:22 +02:00
|
|
|
cell_t *pIsCmd, *pFlags;
|
|
|
|
const char *desc;
|
2008-11-14 16:18:30 +01:00
|
|
|
const ConCommandBase *pConCmd;
|
2008-03-30 09:00:22 +02:00
|
|
|
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
|
|
|
|
|
|
|
if ((err = g_HandleSys.ReadHandle(params[1], htConCmdIter, &sec, (void **)&pIter)) != HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
2010-07-28 00:32:32 +02:00
|
|
|
if (!pIter->IsValid())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-28 00:32:32 +02:00
|
|
|
pIter->Next();
|
|
|
|
if (!pIter->IsValid())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-07-28 00:32:32 +02:00
|
|
|
pConCmd = pIter->Get();
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
pContext->LocalToPhysAddr(params[4], &pIsCmd);
|
|
|
|
pContext->LocalToPhysAddr(params[5], &pFlags);
|
|
|
|
|
2008-11-14 16:18:30 +01:00
|
|
|
pContext->StringToLocalUTF8(params[2], params[3], pConCmd->GetName(), NULL);
|
|
|
|
*pIsCmd = pConCmd->IsCommand() ? 1 : 0;
|
|
|
|
*pFlags = pConCmd->GetFlags();
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
if (params[7])
|
|
|
|
{
|
2008-11-14 16:18:30 +01:00
|
|
|
desc = pConCmd->GetHelpText();
|
2008-03-30 09:00:22 +02:00
|
|
|
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));
|
|
|
|
|
2013-01-23 03:43:12 +01:00
|
|
|
#if SOURCE_ENGINE == SE_CSGO
|
|
|
|
CNETMsg_SetConVar msg;
|
|
|
|
CMsg_CVars_CVar *cvar = msg.mutable_convars()->add_cvars();
|
|
|
|
|
|
|
|
cvar->set_name(pConVar->GetName());
|
|
|
|
cvar->set_value(value);
|
|
|
|
|
|
|
|
buffer.WriteVarInt32(net_SetConVar);
|
|
|
|
buffer.WriteVarInt32(msg.ByteSize());
|
|
|
|
msg.SerializeWithCachedSizesToArray( (uint8 *)( buffer.GetBasePointer() + buffer.GetNumBytesWritten() ) );
|
|
|
|
#else
|
2010-05-05 04:53:26 +02:00
|
|
|
buffer.WriteUBitLong(NET_SETCONVAR, NETMSG_BITS);
|
2008-03-30 09:00:22 +02:00
|
|
|
buffer.WriteByte(1);
|
|
|
|
buffer.WriteString(pConVar->GetName());
|
|
|
|
buffer.WriteString(value);
|
2013-01-23 03:43:12 +01:00
|
|
|
#endif
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
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]));
|
2010-04-28 08:40:04 +02:00
|
|
|
if (netchan == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
netchan->SendData(buffer);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-03-04 23:59:49 +01:00
|
|
|
static cell_t AddServerTag(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
2009-03-25 08:27:32 +01:00
|
|
|
return 0;
|
2009-03-04 23:59:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t RemoveServerTag(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-26 23:12:23 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-03-30 09:00:22 +02:00
|
|
|
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},
|
2010-07-07 00:32:58 +02:00
|
|
|
{"GetConVarDefault", GetConVarDefault},
|
2008-03-30 09:00:22 +02:00
|
|
|
{"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},
|
2011-07-18 04:23:03 +02:00
|
|
|
{"ServerCommandEx", sm_ServerCommandEx},
|
2008-03-30 09:00:22 +02:00
|
|
|
{"InsertServerCommand", sm_InsertServerCommand},
|
|
|
|
{"ServerExecute", sm_ServerExecute},
|
|
|
|
{"ClientCommand", sm_ClientCommand},
|
|
|
|
{"FakeClientCommand", FakeClientCommand},
|
|
|
|
{"ReplyToCommand", ReplyToCommand},
|
|
|
|
{"GetCmdReplySource", GetCmdReplyTarget},
|
|
|
|
{"SetCmdReplySource", SetCmdReplyTarget},
|
|
|
|
{"GetCommandIterator", GetCommandIterator},
|
|
|
|
{"ReadCommandIterator", ReadCommandIterator},
|
|
|
|
{"CheckCommandAccess", CheckCommandAccess},
|
2011-09-10 18:08:38 +02:00
|
|
|
{"CheckAccess", CheckAccess},
|
2008-03-30 09:00:22 +02:00
|
|
|
{"FakeClientCommandEx", FakeClientCommandEx},
|
|
|
|
{"IsChatTrigger", IsChatTrigger},
|
|
|
|
{"SetCommandFlags", SetCommandFlags},
|
|
|
|
{"GetCommandFlags", GetCommandFlags},
|
|
|
|
{"FindFirstConCommand", FindFirstConCommand},
|
|
|
|
{"FindNextConCommand", FindNextConCommand},
|
|
|
|
{"SendConVarValue", SendConVarValue},
|
2009-03-04 23:59:49 +01:00
|
|
|
{"AddServerTag", AddServerTag},
|
|
|
|
{"RemoveServerTag", RemoveServerTag},
|
2009-09-26 23:12:23 +02:00
|
|
|
{"AddCommandListener", AddCommandListener},
|
|
|
|
{"RemoveCommandListener", RemoveCommandListener},
|
2008-03-30 09:00:22 +02:00
|
|
|
{NULL, NULL}
|
|
|
|
};
|