Triggered build, something funky happened....
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_globals.h"
33 #include "HalfLife2.h"
34 #include "sourcemm_api.h"
35 #include "HandleSys.h"
36 #include "ConVarManager.h"
37 #include "ConCmdManager.h"
38 #include "PluginSys.h"
39 #include "sm_stringutil.h"
40 #include "PlayerManager.h"
41 #include "ChatTriggers.h"
42 #include "AdminCache.h"
43 #include <inetchannel.h>
45 #include <sm_trie_tpl.h>
47 #if SOURCE_ENGINE == SE_LEFT4DEAD
48 #define NET_SETCONVAR 6
50 #define NET_SETCONVAR 5
55 ConVarBound_Upper = 0,
59 HandleType_t hCmdIterType = 0;
60 HandleType_t htConCmdIter = 0;
65 List<ConCmdInfo *>::iterator iter;
70 #if SOURCE_ENGINE == SE_LEFT4DEAD
71 ICvarIteratorInternal *pLast;
73 const ConCommandBase *pLast;
77 class ConsoleHelpers :
79 public IHandleTypeDispatch
82 virtual void OnSourceModAllInitialized()
86 g_HandleSys.InitAccessDefaults(NULL, &access);
88 htConCmdIter = g_HandleSys.CreateType("ConCmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
90 access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER | HANDLE_RESTRICT_IDENTITY;
92 hCmdIterType = g_HandleSys.CreateType("CmdIter", this, 0, NULL, &access, g_pCoreIdent, NULL);
94 virtual void OnHandleDestroy(HandleType_t type, void *object)
96 if (type == hCmdIterType)
98 GlobCmdIter *iter = (GlobCmdIter *)object;
101 else if (type == htConCmdIter)
103 ConCmdIter *iter = (ConCmdIter * )object;
107 virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
109 if (type == htConCmdIter)
111 *pSize = sizeof(ConCmdIter);
114 else if (type == hCmdIterType)
116 *pSize = sizeof(GlobCmdIter);
123 class CommandFlagsHelper : public IConCommandTracker
126 void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
128 m_CmdFlags.remove(name);
130 bool GetFlags(const char *name, int *flags)
132 ConCommandBase **ppCmd;
133 ConCommandBase *pCmd;
134 if ((ppCmd=m_CmdFlags.retrieve(name)))
136 TrackConCommandBase((*ppCmd), this);
137 *flags = (*ppCmd)->GetFlags();
140 else if ((pCmd=FindCommandBase(name)))
142 m_CmdFlags.insert(name, pCmd);
143 TrackConCommandBase(pCmd, this);
144 *flags = pCmd->GetFlags();
152 bool SetFlags(const char *name, int flags)
154 ConCommandBase **ppCmd;
155 ConCommandBase *pCmd;
156 if ((ppCmd=m_CmdFlags.retrieve(name)))
158 (*ppCmd)->SetFlags(flags);
159 TrackConCommandBase((*ppCmd), this);
162 else if ((pCmd=FindCommandBase(name)))
164 m_CmdFlags.insert(name, pCmd);
165 pCmd->SetFlags(flags);
166 TrackConCommandBase(pCmd, this);
175 KTrie<ConCommandBase *> m_CmdFlags;
176 } s_CommandFlagsHelper;
178 #if SOURCE_ENGINE >= SE_ORANGEBOX
179 static void ReplicateConVar(ConVar *pConVar)
181 int maxClients = g_Players.GetMaxClients();
184 bf_write buffer(data, sizeof(data));
186 buffer.WriteUBitLong(NET_SETCONVAR, 5);
188 buffer.WriteString(pConVar->GetName());
189 buffer.WriteString(pConVar->GetString());
191 for (int i = 1; i <= maxClients; i++)
193 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
195 if (pPlayer && pPlayer->IsInGame() && !pPlayer->IsFakeClient())
197 INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(i));
198 netchan->SendData(buffer);
203 static void NotifyConVar(ConVar *pConVar)
205 IGameEvent *pEvent = gameevents->CreateEvent("server_cvar");
206 pEvent->SetString("cvarname", pConVar->GetName());
207 if (IsFlagSet(pConVar, FCVAR_PROTECTED))
209 pEvent->SetString("cvarvalue", "***PROTECTED***");
213 pEvent->SetString("cvarvalue", pConVar->GetString());
216 gameevents->FireEvent(pEvent);
220 static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params)
222 char *name, *defaultVal, *helpText;
224 pContext->LocalToString(params[1], &name);
226 // While the engine seems to accept a blank convar name, it causes a crash upon server quit
227 if (name == NULL || strcmp(name, "") == 0)
229 return pContext->ThrowNativeError("Convar with blank name is not permitted");
232 pContext->LocalToString(params[2], &defaultVal);
233 pContext->LocalToString(params[3], &helpText);
235 bool hasMin = params[5] ? true : false;
236 bool hasMax = params[7] ? true : false;
237 float min = sp_ctof(params[6]);
238 float max = sp_ctof(params[8]);
240 Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max);
242 if (hndl == BAD_HANDLE)
244 return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name);
250 static cell_t sm_FindConVar(IPluginContext *pContext, const cell_t *params)
254 pContext->LocalToString(params[1], &name);
256 return g_ConVarManager.FindConVar(name);
259 static cell_t sm_HookConVarChange(IPluginContext *pContext, const cell_t *params)
261 Handle_t hndl = static_cast<Handle_t>(params[1]);
265 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
268 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
271 IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
275 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
278 g_ConVarManager.HookConVarChange(pConVar, pFunction);
283 static cell_t sm_UnhookConVarChange(IPluginContext *pContext, const cell_t *params)
285 Handle_t hndl = static_cast<Handle_t>(params[1]);
289 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
292 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
295 IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
299 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
302 g_ConVarManager.UnhookConVarChange(pConVar, pFunction);
307 static cell_t sm_GetConVarBool(IPluginContext *pContext, const cell_t *params)
309 Handle_t hndl = static_cast<Handle_t>(params[1]);
313 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
316 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
319 return pConVar->GetBool();
322 static cell_t sm_GetConVarInt(IPluginContext *pContext, const cell_t *params)
324 Handle_t hndl = static_cast<Handle_t>(params[1]);
328 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
331 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
334 return pConVar->GetInt();
337 /* This handles both SetConVarBool() and SetConVarInt() */
338 static cell_t sm_SetConVarNum(IPluginContext *pContext, const cell_t *params)
340 Handle_t hndl = static_cast<Handle_t>(params[1]);
344 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
347 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
350 pConVar->SetValue(params[2]);
352 #if SOURCE_ENGINE >= SE_ORANGEBOX
353 /* Should we replicate it? */
354 if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
356 ReplicateConVar(pConVar);
359 /* Should we notify clients? */
360 if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
362 NotifyConVar(pConVar);
369 static cell_t sm_GetConVarFloat(IPluginContext *pContext, const cell_t *params)
371 Handle_t hndl = static_cast<Handle_t>(params[1]);
375 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
378 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
381 float value = pConVar->GetFloat();
383 return sp_ftoc(value);
386 static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params)
388 Handle_t hndl = static_cast<Handle_t>(params[1]);
392 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
395 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
398 float value = sp_ctof(params[2]);
399 pConVar->SetValue(value);
401 #if SOURCE_ENGINE >= SE_ORANGEBOX
402 /* Should we replicate it? */
403 if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
405 ReplicateConVar(pConVar);
408 /* Should we notify clients? */
409 if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
411 NotifyConVar(pConVar);
418 static cell_t sm_GetConVarString(IPluginContext *pContext, const cell_t *params)
420 Handle_t hndl = static_cast<Handle_t>(params[1]);
424 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
427 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
430 pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetString(), NULL);
435 static cell_t sm_SetConVarString(IPluginContext *pContext, const cell_t *params)
437 Handle_t hndl = static_cast<Handle_t>(params[1]);
441 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
444 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
448 pContext->LocalToString(params[2], &value);
450 pConVar->SetValue(value);
452 #if SOURCE_ENGINE >= SE_ORANGEBOX
453 /* Should we replicate it? */
454 if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
456 ReplicateConVar(pConVar);
459 /* Should we notify clients? */
460 if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
462 NotifyConVar(pConVar);
469 static cell_t sm_ResetConVar(IPluginContext *pContext, const cell_t *params)
471 Handle_t hndl = static_cast<Handle_t>(params[1]);
475 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
478 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
483 #if SOURCE_ENGINE >= SE_ORANGEBOX
484 /* Should we replicate it? */
485 if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED))
487 ReplicateConVar(pConVar);
490 /* Should we notify clients? */
491 if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY))
493 NotifyConVar(pConVar);
500 static cell_t sm_GetConVarFlags(IPluginContext *pContext, const cell_t *params)
502 Handle_t hndl = static_cast<Handle_t>(params[1]);
506 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
509 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
512 return pConVar->GetFlags();
515 static cell_t sm_SetConVarFlags(IPluginContext *pContext, const cell_t *params)
517 Handle_t hndl = static_cast<Handle_t>(params[1]);
521 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
524 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
527 pConVar->SetFlags(params[2]);
532 static cell_t sm_GetConVarBounds(IPluginContext *pContext, const cell_t *params)
534 Handle_t hndl = static_cast<Handle_t>(params[1]);
538 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
541 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
550 case ConVarBound_Upper:
551 hasBound = pConVar->GetMax(bound);
553 case ConVarBound_Lower:
554 hasBound = pConVar->GetMin(bound);
557 return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
560 pContext->LocalToPhysAddr(params[3], &addr);
561 *addr = sp_ftoc(bound);
566 static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params)
568 Handle_t hndl = static_cast<Handle_t>(params[1]);
572 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
575 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
580 case ConVarBound_Upper:
581 pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4]));
583 case ConVarBound_Lower:
584 pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4]));
587 return pContext->ThrowNativeError("Invalid ConVarBounds value %d");
593 static cell_t sm_GetConVarName(IPluginContext *pContext, const cell_t *params)
595 Handle_t hndl = static_cast<Handle_t>(params[1]);
599 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
602 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
605 pContext->StringToLocalUTF8(params[2], params[3], pConVar->GetName(), NULL);
610 static bool s_QueryAlreadyWarned = false;
612 static cell_t sm_QueryClientConVar(IPluginContext *pContext, const cell_t *params)
616 IPluginFunction *pCallback;
618 if (!g_ConVarManager.IsQueryingSupported())
620 if (!s_QueryAlreadyWarned)
622 s_QueryAlreadyWarned = true;
623 return pContext->ThrowNativeError("Game does not support client convar querying (one time warning)");
629 pPlayer = g_Players.GetPlayerByIndex(params[1]);
633 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
636 if (!pPlayer->IsConnected())
638 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
641 /* Trying a query on a bot results in callback not be fired, so don't bother */
642 if (pPlayer->IsFakeClient())
647 pContext->LocalToString(params[2], &name);
648 pCallback = pContext->GetFunctionById(params[3]);
652 return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
655 return g_ConVarManager.QueryClientConVar(pPlayer->GetEdict(), name, pCallback, params[4]);
658 static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
661 IPluginFunction *pFunction;
663 pContext->LocalToString(params[1], &name);
664 pContext->LocalToString(params[3], &help);
665 pFunction = pContext->GetFunctionById(params[2]);
669 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
672 if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4]))
674 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
680 static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
683 IPluginFunction *pFunction;
685 pContext->LocalToString(params[1], &name);
686 pContext->LocalToString(params[3], &help);
687 pFunction = pContext->GetFunctionById(params[2]);
691 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
694 if (!g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]))
696 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
702 static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
706 IPluginFunction *pFunction;
707 FlagBits flags = params[3];
708 int cmdflags = params[6];
710 pContext->LocalToString(params[1], &name);
711 pContext->LocalToString(params[4], &help);
712 pContext->LocalToString(params[5], (char **)&group);
713 pFunction = pContext->GetFunctionById(params[2]);
715 if (group[0] == '\0')
717 CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
718 group = pPlugin->GetFilename();
723 return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
726 if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags))
728 return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
734 static cell_t sm_GetCmdArgs(IPluginContext *pContext, const cell_t *params)
736 const CCommand *pCmd = g_HL2.PeekCommandStack();
740 return pContext->ThrowNativeError("No command callback available");
743 return pCmd->ArgC() - 1;
746 static cell_t sm_GetCmdArg(IPluginContext *pContext, const cell_t *params)
748 const CCommand *pCmd = g_HL2.PeekCommandStack();
752 return pContext->ThrowNativeError("No command callback available");
757 const char *arg = pCmd->Arg(params[1]);
759 pContext->StringToLocalUTF8(params[2], params[3], arg ? arg : "", &length);
761 return (cell_t)length;
764 static cell_t sm_GetCmdArgString(IPluginContext *pContext, const cell_t *params)
766 const CCommand *pCmd = g_HL2.PeekCommandStack();
770 return pContext->ThrowNativeError("No command callback available");
773 const char *args = pCmd->ArgS();
781 pContext->StringToLocalUTF8(params[1], params[2], args, &length);
783 return (cell_t)length;
786 static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params)
792 pCtx->LocalToString(params[1], &fmt);
793 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
795 buffer[res++] = '\n';
798 META_CONPRINT(buffer);
803 static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
805 int index = params[1];
806 if ((index < 0) || (index > g_Players.GetMaxClients()))
808 return pCtx->ThrowNativeError("Client index %d is invalid", index);
811 CPlayer *pPlayer = NULL;
814 pPlayer = g_Players.GetPlayerByIndex(index);
815 if (!pPlayer->IsInGame())
817 return pCtx->ThrowNativeError("Client %d is not in game", index);
820 /* Silent fail on bots, engine will crash */
821 if (pPlayer->IsFakeClient())
831 pCtx->LocalToString(params[2], &fmt);
832 size_t res = atcprintf(buffer, sizeof(buffer)-2, fmt, pCtx, params, &arg);
834 buffer[res++] = '\n';
839 engine->ClientPrintf(pPlayer->GetEdict(), buffer);
841 META_CONPRINT(buffer);
847 static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
849 g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
852 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
854 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
859 /* One byte for null terminator, one for newline */
860 buffer[len++] = '\n';
863 engine->ServerCommand(buffer);
868 static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
870 g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
873 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
875 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
880 /* One byte for null terminator, one for newline */
881 buffer[len++] = '\n';
884 InsertServerCommand(buffer);
889 static cell_t sm_ServerExecute(IPluginContext *pContext, const cell_t *params)
891 engine->ServerExecute();
896 static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
898 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
902 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
905 if (!pPlayer->IsConnected())
907 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
910 g_SourceMod.SetGlobalTarget(params[1]);
913 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
915 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
920 engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
925 static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
927 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
931 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
934 if (!pPlayer->IsConnected())
936 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
940 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
942 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
947 serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
952 static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params)
954 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
958 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
961 if (!pPlayer->IsConnected())
963 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
967 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
969 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
974 g_HL2.AddToFakeCliCmdQueue(params[1], engine->GetPlayerUserId(pPlayer->GetEdict()), buffer);
979 static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
981 g_SourceMod.SetGlobalTarget(params[1]);
983 /* Build the format string */
985 size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
987 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
992 /* If we're printing to the server, shortcut out */
996 buffer[len++] = '\n';
998 META_CONPRINT(buffer);
1002 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1006 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1009 if (!pPlayer->IsConnected())
1011 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1014 g_SourceMod.SetGlobalTarget(params[1]);
1016 unsigned int replyto = g_ChatTriggers.GetReplyTo();
1017 if (replyto == SM_REPLY_CONSOLE)
1019 buffer[len++] = '\n';
1021 engine->ClientPrintf(pPlayer->GetEdict(), buffer);
1022 } else if (replyto == SM_REPLY_CHAT) {
1028 g_HL2.TextMsg(params[1], HUD_PRINTTALK, buffer);
1034 static cell_t GetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
1036 return g_ChatTriggers.GetReplyTo();
1039 static cell_t SetCmdReplyTarget(IPluginContext *pContext, const cell_t *params)
1041 return g_ChatTriggers.SetReplyTo(params[1]);
1044 static cell_t GetCommandIterator(IPluginContext *pContext, const cell_t *params)
1046 GlobCmdIter *iter = new GlobCmdIter;
1047 iter->started = false;
1049 Handle_t hndl = g_HandleSys.CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
1050 if (hndl == BAD_HANDLE)
1058 static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params)
1062 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1064 if ((err = g_HandleSys.ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
1065 != HandleError_None)
1067 return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]);
1070 const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
1074 iter->iter = cmds.begin();
1075 iter->started = true;
1078 while (iter->iter != cmds.end()
1079 && !(*(iter->iter))->sourceMod)
1084 if (iter->iter == cmds.end())
1089 ConCmdInfo *pInfo = (*(iter->iter));
1091 pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
1092 pContext->StringToLocalUTF8(params[5], params[6], pInfo->pCmd->GetHelpText(), NULL);
1095 pContext->LocalToPhysAddr(params[4], &addr);
1096 *addr = pInfo->admin.eflags;
1103 static cell_t CheckCommandAccess(IPluginContext *pContext, const cell_t *params)
1111 pContext->LocalToString(params[2], &cmd);
1113 /* Auto-detect a command if we can */
1114 FlagBits bits = params[3];
1115 bool found_command = false;
1116 if (params[0] < 4 || !params[4])
1118 found_command = g_ConCmds.LookForCommandAdminFlags(cmd, &bits);
1123 g_Admins.GetCommandOverride(cmd, Override_Command, &bits);
1126 return g_ConCmds.CheckCommandAccess(params[1], cmd, bits) ? 1 : 0;
1129 static cell_t IsChatTrigger(IPluginContext *pContext, const cell_t *params)
1131 return g_ChatTriggers.IsChatTrigger() ? 1 : 0;
1134 static cell_t SetCommandFlags(IPluginContext *pContext, const cell_t *params)
1137 pContext->LocalToString(params[1], &name);
1139 return (s_CommandFlagsHelper.SetFlags(name, params[2])) ? 1 : 0;
1142 static cell_t GetCommandFlags(IPluginContext *pContext, const cell_t *params)
1146 pContext->LocalToString(params[1], &name);
1148 return (s_CommandFlagsHelper.GetFlags(name, &flags)) ? flags : -1;
1151 static cell_t FindFirstConCommand(IPluginContext *pContext, const cell_t *params)
1155 cell_t *pIsCmd, *pFlags;
1156 const ConCommandBase *pConCmd;
1159 pContext->LocalToPhysAddr(params[3], &pIsCmd);
1160 pContext->LocalToPhysAddr(params[4], &pFlags);
1162 #if SOURCE_ENGINE == SE_LEFT4DEAD
1163 ICvarIteratorInternal *cvarIter = icvar->FactoryInternalIterator();
1164 cvarIter->SetFirst();
1165 if (!cvarIter->IsValid())
1169 pConCmd = cvarIter->Get();
1171 pConCmd = icvar->GetCommands();
1172 if (pConCmd == NULL)
1178 pContext->StringToLocalUTF8(params[1], params[2], pConCmd->GetName(), NULL);
1179 *pIsCmd = pConCmd->IsCommand() ? 1 : 0;
1180 *pFlags = pConCmd->GetFlags();
1184 desc = pConCmd->GetHelpText();
1185 pContext->StringToLocalUTF8(params[5], params[6], (desc && desc[0]) ? desc : "", NULL);
1188 pIter = new ConCmdIter;
1189 #if SOURCE_ENGINE == SE_LEFT4DEAD
1190 pIter->pLast = cvarIter;
1192 pIter->pLast = pConCmd;
1195 if ((hndl = g_HandleSys.CreateHandle(htConCmdIter, pIter, pContext->GetIdentity(), g_pCoreIdent, NULL))
1205 static cell_t FindNextConCommand(IPluginContext *pContext, const cell_t *params)
1209 cell_t *pIsCmd, *pFlags;
1211 const ConCommandBase *pConCmd;
1212 HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
1214 if ((err = g_HandleSys.ReadHandle(params[1], htConCmdIter, &sec, (void **)&pIter)) != HandleError_None)
1216 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
1219 if (pIter->pLast == NULL)
1224 #if SOURCE_ENGINE == SE_LEFT4DEAD
1225 ICvarIteratorInternal *cvarIter = pIter->pLast;
1227 if (!cvarIter->IsValid())
1231 pConCmd = cvarIter->Get();
1233 pConCmd = pIter->pLast->GetNext();
1234 if (pConCmd == NULL)
1238 pIter->pLast = pConCmd;
1241 pContext->LocalToPhysAddr(params[4], &pIsCmd);
1242 pContext->LocalToPhysAddr(params[5], &pFlags);
1244 pContext->StringToLocalUTF8(params[2], params[3], pConCmd->GetName(), NULL);
1245 *pIsCmd = pConCmd->IsCommand() ? 1 : 0;
1246 *pFlags = pConCmd->GetFlags();
1250 desc = pConCmd->GetHelpText();
1251 pContext->StringToLocalUTF8(params[6], params[7], (desc && desc[0]) ? desc : "", NULL);
1257 static cell_t SendConVarValue(IPluginContext *pContext, const cell_t *params)
1259 Handle_t hndl = static_cast<Handle_t>(params[2]);
1264 pContext->LocalToString(params[3], &value);
1266 if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
1267 != HandleError_None)
1269 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
1273 bf_write buffer(data, sizeof(data));
1275 buffer.WriteUBitLong(NET_SETCONVAR, 5);
1276 buffer.WriteByte(1);
1277 buffer.WriteString(pConVar->GetName());
1278 buffer.WriteString(value);
1280 CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1284 return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1287 if (!pPlayer->IsConnected())
1289 return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1292 if (pPlayer->IsFakeClient())
1294 return pContext->ThrowNativeError("Client %d is fake and cannot be targeted", params[1]);
1297 INetChannel *netchan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
1298 netchan->SendData(buffer);
1303 REGISTER_NATIVES(consoleNatives)
1305 {"CreateConVar", sm_CreateConVar},
1306 {"FindConVar", sm_FindConVar},
1307 {"HookConVarChange", sm_HookConVarChange},
1308 {"UnhookConVarChange", sm_UnhookConVarChange},
1309 {"GetConVarBool", sm_GetConVarBool},
1310 {"SetConVarBool", sm_SetConVarNum},
1311 {"GetConVarInt", sm_GetConVarInt},
1312 {"SetConVarInt", sm_SetConVarNum},
1313 {"GetConVarFloat", sm_GetConVarFloat},
1314 {"SetConVarFloat", sm_SetConVarFloat},
1315 {"GetConVarString", sm_GetConVarString},
1316 {"SetConVarString", sm_SetConVarString},
1317 {"GetConVarFlags", sm_GetConVarFlags},
1318 {"SetConVarFlags", sm_SetConVarFlags},
1319 {"ResetConVar", sm_ResetConVar},
1320 {"GetConVarName", sm_GetConVarName},
1321 {"GetConVarBounds", sm_GetConVarBounds},
1322 {"SetConVarBounds", sm_SetConVarBounds},
1323 {"QueryClientConVar", sm_QueryClientConVar},
1324 {"RegServerCmd", sm_RegServerCmd},
1325 {"RegConsoleCmd", sm_RegConsoleCmd},
1326 {"GetCmdArgString", sm_GetCmdArgString},
1327 {"GetCmdArgs", sm_GetCmdArgs},
1328 {"GetCmdArg", sm_GetCmdArg},
1329 {"PrintToServer", sm_PrintToServer},
1330 {"PrintToConsole", sm_PrintToConsole},
1331 {"RegAdminCmd", sm_RegAdminCmd},
1332 {"ServerCommand", sm_ServerCommand},
1333 {"InsertServerCommand", sm_InsertServerCommand},
1334 {"ServerExecute", sm_ServerExecute},
1335 {"ClientCommand", sm_ClientCommand},
1336 {"FakeClientCommand", FakeClientCommand},
1337 {"ReplyToCommand", ReplyToCommand},
1338 {"GetCmdReplySource", GetCmdReplyTarget},
1339 {"SetCmdReplySource", SetCmdReplyTarget},
1340 {"GetCommandIterator", GetCommandIterator},
1341 {"ReadCommandIterator", ReadCommandIterator},
1342 {"CheckCommandAccess", CheckCommandAccess},
1343 {"FakeClientCommandEx", FakeClientCommandEx},
1344 {"IsChatTrigger", IsChatTrigger},
1345 {"SetCommandFlags", SetCommandFlags},
1346 {"GetCommandFlags", GetCommandFlags},
1347 {"FindFirstConCommand", FindFirstConCommand},
1348 {"FindNextConCommand", FindNextConCommand},
1349 {"SendConVarValue", SendConVarValue},