Added ProcessTargetString simple filter API (bug 4404, r=ds).
1.1 --- a/core/logic/AMBuilder Thu May 13 04:54:31 2010 -0500
1.2 +++ b/core/logic/AMBuilder Thu May 13 12:28:51 2010 -0700
1.3 @@ -31,6 +31,7 @@
1.4 'Profiler.cpp',
1.5 'smn_functions.cpp',
1.6 'smn_timers.cpp',
1.7 + 'smn_players.cpp',
1.8 'sm_crc32.cpp'
1.9 ]
1.10 if AMBuild.target['platform'] == 'windows':
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/core/logic/AutoHandleRooter.h Thu May 13 12:28:51 2010 -0700
2.3 @@ -0,0 +1,92 @@
2.4 +/**
2.5 + * vim: set ts=4 sw=4 tw=99 noet :
2.6 + * =============================================================================
2.7 + * SourceMod
2.8 + * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
2.9 + * =============================================================================
2.10 + *
2.11 + * This program is free software; you can redistribute it and/or modify it under
2.12 + * the terms of the GNU General Public License, version 3.0, as published by the
2.13 + * Free Software Foundation.
2.14 + *
2.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
2.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2.18 + * details.
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License along with
2.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
2.22 + *
2.23 + * As a special exception, AlliedModders LLC gives you permission to link the
2.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
2.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
2.26 + * by the Valve Corporation. You must obey the GNU General Public License in
2.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
2.28 + * this exception to all derivative works. AlliedModders LLC defines further
2.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
2.30 + * or <http://www.sourcemod.net/license.php>.
2.31 + *
2.32 + * Version: $Id$
2.33 + */
2.34 +
2.35 +#ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
2.36 +#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
2.37 +
2.38 +#include "common_logic.h"
2.39 +#include <IHandleSys.h>
2.40 +
2.41 +class AutoHandleRooter
2.42 +{
2.43 +public:
2.44 + AutoHandleRooter(Handle_t hndl)
2.45 + {
2.46 + if (hndl != BAD_HANDLE)
2.47 + this->hndl = handlesys->FastCloneHandle(hndl);
2.48 + else
2.49 + this->hndl = BAD_HANDLE;
2.50 + }
2.51 +
2.52 + ~AutoHandleRooter()
2.53 + {
2.54 + if (hndl != BAD_HANDLE)
2.55 + {
2.56 + HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
2.57 + handlesys->FreeHandle(hndl, &sec);
2.58 + }
2.59 + }
2.60 +
2.61 + Handle_t getHandle()
2.62 + {
2.63 + return hndl;
2.64 + }
2.65 +private:
2.66 + Handle_t hndl;
2.67 +};
2.68 +
2.69 +class AutoHandleCloner
2.70 +{
2.71 + Handle_t original;
2.72 + HandleSecurity sec;
2.73 + AutoHandleRooter ahr;
2.74 +public:
2.75 + AutoHandleCloner(Handle_t original, HandleSecurity sec)
2.76 + : original(original), sec(sec), ahr(original)
2.77 + {
2.78 + }
2.79 +
2.80 + ~AutoHandleCloner()
2.81 + {
2.82 + if (original != BAD_HANDLE)
2.83 + {
2.84 + handlesys->FreeHandle(original, &sec);
2.85 + }
2.86 + }
2.87 +
2.88 + Handle_t getClone()
2.89 + {
2.90 + return ahr.getHandle();
2.91 + }
2.92 +};
2.93 +
2.94 +#endif /* _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ */
2.95 +
3.1 --- a/core/logic/Makefile Thu May 13 04:54:31 2010 -0500
3.2 +++ b/core/logic/Makefile Thu May 13 12:28:51 2010 -0700
3.3 @@ -27,7 +27,8 @@
3.4 Profiler.cpp \
3.5 smn_functions.cpp \
3.6 sm_crc32.cpp \
3.7 - smn_timers.cpp
3.8 + smn_timers.cpp \
3.9 + smn_players.cpp
3.10
3.11 ##############################################
3.12 ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
4.1 --- a/core/logic/common_logic.cpp Thu May 13 04:54:31 2010 -0500
4.2 +++ b/core/logic/common_logic.cpp Thu May 13 12:28:51 2010 -0700
4.3 @@ -52,6 +52,7 @@
4.4 IForwardManager *forwardsys;
4.5 ITimerSystem *timersys;
4.6 ServerGlobals serverGlobals;
4.7 +IPlayerManager *playerhelpers;
4.8
4.9 static sm_logic_t logic =
4.10 {
4.11 @@ -79,6 +80,7 @@
4.12 pluginsys = core->pluginsys;
4.13 forwardsys = core->forwardsys;
4.14 timersys = core->timersys;
4.15 + playerhelpers = core->playerhelpers;
4.16 }
4.17
4.18 PLATFORM_EXTERN_C ITextParsers *get_textparsers()
5.1 --- a/core/logic/common_logic.h Thu May 13 04:54:31 2010 -0500
5.2 +++ b/core/logic/common_logic.h Thu May 13 12:28:51 2010 -0700
5.3 @@ -49,6 +49,7 @@
5.4 extern IForwardManager *forwardsys;
5.5 extern ITimerSystem *timersys;
5.6 extern ServerGlobals serverGlobals;
5.7 +extern IPlayerManager *playerhelpers;
5.8
5.9 #endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
5.10
6.1 --- a/core/logic/intercom.h Thu May 13 04:54:31 2010 -0500
6.2 +++ b/core/logic/intercom.h Thu May 13 12:28:51 2010 -0700
6.3 @@ -42,7 +42,7 @@
6.4 * Add 1 to the RHS of this expression to bump the intercom file
6.5 * This is to prevent mismatching core/logic binaries
6.6 */
6.7 -#define SM_LOGIC_MAGIC (0x0F47C0DE - 4)
6.8 +#define SM_LOGIC_MAGIC (0x0F47C0DE - 5)
6.9
6.10 #if defined SM_LOGIC
6.11 class IVEngineServer
6.12 @@ -64,6 +64,7 @@
6.13 class IPluginManager;
6.14 class IForwardManager;
6.15 class ITimerSystem;
6.16 + class IPlayerManager;
6.17 }
6.18
6.19 class IVEngineServer;
6.20 @@ -89,6 +90,7 @@
6.21 IPluginManager *pluginsys;
6.22 IForwardManager *forwardsys;
6.23 ITimerSystem *timersys;
6.24 + IPlayerManager *playerhelpers;
6.25 /* Functions */
6.26 void (*AddNatives)(sp_nativeinfo_t* nlist);
6.27 ConVar * (*FindConVar)(const char*);
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/core/logic/smn_players.cpp Thu May 13 12:28:51 2010 -0700
7.3 @@ -0,0 +1,235 @@
7.4 +/**
7.5 + * vim: set ts=4 sw=4 tw=99 noet :
7.6 + * =============================================================================
7.7 + * SourceMod
7.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
7.9 + * =============================================================================
7.10 + *
7.11 + * This program is free software; you can redistribute it and/or modify it under
7.12 + * the terms of the GNU General Public License, version 3.0, as published by the
7.13 + * Free Software Foundation.
7.14 + *
7.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
7.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
7.18 + * details.
7.19 + *
7.20 + * You should have received a copy of the GNU General Public License along with
7.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
7.22 + *
7.23 + * As a special exception, AlliedModders LLC gives you permission to link the
7.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
7.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
7.26 + * by the Valve Corporation. You must obey the GNU General Public License in
7.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
7.28 + * this exception to all derivative works. AlliedModders LLC defines further
7.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
7.30 + * or <http://www.sourcemod.net/license.php>.
7.31 + *
7.32 + * Version: $Id$
7.33 + */
7.34 +
7.35 +#include "common_logic.h"
7.36 +#include <IPluginSys.h>
7.37 +#include <IPlayerHelpers.h>
7.38 +#include <sh_string.h>
7.39 +#include <sh_list.h>
7.40 +#include "AutoHandleRooter.h"
7.41 +#include "CellArray.h"
7.42 +
7.43 +using namespace SourceHook;
7.44 +using namespace SourceMod;
7.45 +
7.46 +class PlayerLogicHelpers :
7.47 + public SMGlobalClass,
7.48 + public IPluginsListener,
7.49 + public ICommandTargetProcessor
7.50 +{
7.51 + struct SimpleMultiTargetFilter
7.52 + {
7.53 + IPlugin *plugin;
7.54 + SourceHook::String pattern;
7.55 + IPluginFunction *fun;
7.56 + SourceHook::String phrase;
7.57 + bool phraseIsML;
7.58 +
7.59 + SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
7.60 + const char *phrase, bool phraseIsML)
7.61 + : plugin(plugin), pattern(pattern), fun(fun), phrase(phrase), phraseIsML(phraseIsML)
7.62 + {
7.63 + }
7.64 + };
7.65 +
7.66 + List<SimpleMultiTargetFilter *> simpleMultis;
7.67 + bool filterEnabled;
7.68 +
7.69 +public:
7.70 + void AddMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
7.71 + const char *phrase, bool phraseIsML)
7.72 + {
7.73 + SimpleMultiTargetFilter *smtf = new SimpleMultiTargetFilter(plugin, pattern, fun, phrase,
7.74 + phraseIsML);
7.75 +
7.76 + simpleMultis.push_back(smtf);
7.77 +
7.78 + if (!filterEnabled) {
7.79 + playerhelpers->RegisterCommandTargetProcessor(this);
7.80 + filterEnabled = true;
7.81 + }
7.82 + }
7.83 +
7.84 + void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun)
7.85 + {
7.86 + List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
7.87 +
7.88 + while (iter != simpleMultis.end()) {
7.89 + if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) {
7.90 + delete (*iter);
7.91 + iter = simpleMultis.erase(iter);
7.92 + break;
7.93 + }
7.94 + iter++;
7.95 + }
7.96 + }
7.97 +
7.98 + PlayerLogicHelpers()
7.99 + : filterEnabled(false)
7.100 + {
7.101 + }
7.102 +
7.103 +public: //ICommandTargetProcessor
7.104 + bool ProcessCommandTarget(cmd_target_info_t *info)
7.105 + {
7.106 + List<SimpleMultiTargetFilter *>::iterator iter;
7.107 +
7.108 + for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) {
7.109 + SimpleMultiTargetFilter *smtf = (*iter);
7.110 + if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) {
7.111 + CellArray *array = new CellArray(1);
7.112 + HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
7.113 + Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
7.114 + AutoHandleCloner ahc(hndl, sec);
7.115 + if (ahc.getClone() == BAD_HANDLE) {
7.116 + smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
7.117 + delete array;
7.118 + return false;
7.119 + }
7.120 +
7.121 + smtf->fun->PushString(info->pattern);
7.122 + smtf->fun->PushCell(ahc.getClone());
7.123 + cell_t result = 0;
7.124 + if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
7.125 + return false;
7.126 +
7.127 + IGamePlayer *pAdmin = info->admin
7.128 + ? playerhelpers->GetGamePlayer(info->admin)
7.129 + : NULL;
7.130 +
7.131 + info->num_targets = 0;
7.132 + for (size_t i = 0; i < array->size(); i++) {
7.133 + cell_t client = *array->at(i);
7.134 + IGamePlayer *pClient = playerhelpers->GetGamePlayer(client);
7.135 + if (pClient == NULL || !pClient->IsConnected())
7.136 + continue;
7.137 + if (playerhelpers->FilterCommandTarget(pAdmin, pClient, info->flags) ==
7.138 + COMMAND_TARGET_VALID)
7.139 + {
7.140 + info->targets[info->num_targets++] = client;
7.141 + if (info->num_targets >= unsigned(info->max_targets))
7.142 + break;
7.143 + }
7.144 + }
7.145 +
7.146 + info->reason = info->num_targets > 0
7.147 + ? COMMAND_TARGET_VALID
7.148 + : COMMAND_TARGET_EMPTY_FILTER;
7.149 + if (info->num_targets) {
7.150 + smcore.strncopy(info->target_name, smtf->phrase.c_str(), info->target_name_maxlength);
7.151 + info->target_name_style = smtf->phraseIsML
7.152 + ? COMMAND_TARGETNAME_ML
7.153 + : COMMAND_TARGETNAME_RAW;
7.154 + }
7.155 +
7.156 + return true;
7.157 + }
7.158 + }
7.159 +
7.160 + return false;
7.161 + }
7.162 +
7.163 +public: //SMGlobalClass
7.164 + void OnSourceModAllInitialized()
7.165 + {
7.166 + pluginsys->AddPluginsListener(this);
7.167 + }
7.168 +
7.169 + void OnSourceModShutdown()
7.170 + {
7.171 + pluginsys->RemovePluginsListener(this);
7.172 + if (filterEnabled) {
7.173 + playerhelpers->UnregisterCommandTargetProcessor(this);
7.174 + filterEnabled = false;
7.175 + }
7.176 + }
7.177 +
7.178 +public: //IPluginsListener
7.179 +
7.180 + void OnPluginDestroyed(IPlugin *plugin)
7.181 + {
7.182 + List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
7.183 +
7.184 + while (iter != simpleMultis.end()) {
7.185 + if ((*iter)->plugin != plugin) {
7.186 + iter++;
7.187 + } else {
7.188 + delete (*iter);
7.189 + iter = simpleMultis.erase(iter);
7.190 + }
7.191 + }
7.192 + }
7.193 +} s_PlayerLogicHelpers;
7.194 +
7.195 +static cell_t
7.196 +AddMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
7.197 +{
7.198 + IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
7.199 + if (fun == NULL)
7.200 + return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
7.201 +
7.202 + char *pattern;
7.203 + char *phrase;
7.204 +
7.205 + ctx->LocalToString(params[1], &pattern);
7.206 + ctx->LocalToString(params[3], &phrase);
7.207 +
7.208 + bool phraseIsML = !!params[4];
7.209 + IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
7.210 +
7.211 + s_PlayerLogicHelpers.AddMultiTargetFilter(plugin, pattern, fun, phrase, phraseIsML);
7.212 +
7.213 + return 1;
7.214 +}
7.215 +
7.216 +static cell_t
7.217 +RemoveMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
7.218 +{
7.219 + IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
7.220 + if (fun == NULL)
7.221 + return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
7.222 +
7.223 + char *pattern;
7.224 +
7.225 + ctx->LocalToString(params[1], &pattern);
7.226 +
7.227 + s_PlayerLogicHelpers.RemoveMultiTargetFilter(pattern, fun);
7.228 +
7.229 + return 1;
7.230 +}
7.231 +
7.232 +REGISTER_NATIVES(playernatives)
7.233 +{
7.234 + {"AddMultiTargetFilter", AddMultiTargetFilter},
7.235 + {"RemoveMultiTargetFilter", RemoveMultiTargetFilter},
7.236 + {NULL, NULL}
7.237 +};
7.238 +
8.1 --- a/core/logic_bridge.cpp Thu May 13 04:54:31 2010 -0500
8.2 +++ b/core/logic_bridge.cpp Thu May 13 12:28:51 2010 -0700
8.3 @@ -46,6 +46,7 @@
8.4 #include "TimerSys.h"
8.5 #include "logic_bridge.h"
8.6 #include "DebugReporter.h"
8.7 +#include "PlayerManager.h"
8.8
8.9 static ILibrary *g_pLogic = NULL;
8.10 static LogicInitFunction logic_init_fn;
8.11 @@ -113,6 +114,7 @@
8.12 &g_PluginSys,
8.13 &g_Forwards,
8.14 &g_Timers,
8.15 + &g_Players,
8.16 /* Functions */
8.17 add_natives,
8.18 find_convar,
9.1 --- a/plugins/include/commandfilters.inc Thu May 13 04:54:31 2010 -0500
9.2 +++ b/plugins/include/commandfilters.inc Thu May 13 12:28:51 2010 -0700
9.3 @@ -132,3 +132,34 @@
9.4 }
9.5 }
9.6 }
9.7 +
9.8 +/**
9.9 + * Adds clients to a multi-target filter.
9.10 + *
9.11 + * @param pattern Pattern name.
9.12 + * @param clients Array to fill with unique, valid client indexes.
9.13 + * @return True if pattern was recognized, false otherwise.
9.14 + */
9.15 +functag public bool:MultiTargetFilter(const String:pattern[], Handle:clients);
9.16 +
9.17 +/**
9.18 + * Adds a multi-target filter function for ProcessTargetString().
9.19 + *
9.20 + * @param pattern Pattern to match (case sensitive).
9.21 + * @param filter Filter function.
9.22 + * @param phrase Descriptive phrase to display on successful match.
9.23 + * @param phraseIsML True if phrase is multi-lingual, false otherwise.
9.24 + * @noreturn
9.25 + */
9.26 +native AddMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter,
9.27 + const String:phrase[], bool:phraseIsML);
9.28 +
9.29 +/**
9.30 + * Removes a multi-target filter function from ProcessTargetString().
9.31 + *
9.32 + * @param pattern Pattern to match (case sensitive).
9.33 + * @param filter Filter function.
9.34 + * @noreturn
9.35 + */
9.36 +native RemoveMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter);
9.37 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/plugins/testsuite/ptstest.sp Thu May 13 12:28:51 2010 -0700
10.3 @@ -0,0 +1,26 @@
10.4 +#include <sourcemod>
10.5 +
10.6 +public Plugin:myinfo =
10.7 +{
10.8 + name = "Test target filters",
10.9 + author = "AlliedModders LLC",
10.10 + description = "Tests target filters",
10.11 + version = "1.0.0.0",
10.12 + url = "http://www.sourcemod.net/"
10.13 +};
10.14 +
10.15 +public OnPluginStart()
10.16 +{
10.17 + AddMultiTargetFilter("@crab", filter, "all players", true)
10.18 +}
10.19 +
10.20 +public bool:filter(const String:pattern[], Handle:clients)
10.21 +{
10.22 + for (new i = 1; i <= MaxClients; i++) {
10.23 + if (IsPlayerInGame(i))
10.24 + PushArrayCell(clients, i)
10.25 + }
10.26 +
10.27 + return true
10.28 +}
10.29 +
11.1 --- a/public/IHandleSys.h Thu May 13 04:54:31 2010 -0500
11.2 +++ b/public/IHandleSys.h Thu May 13 12:28:51 2010 -0700
11.3 @@ -52,7 +52,7 @@
11.4 #include <sp_vm_types.h>
11.5
11.6 #define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys"
11.7 -#define SMINTERFACE_HANDLESYSTEM_VERSION 3
11.8 +#define SMINTERFACE_HANDLESYSTEM_VERSION 4
11.9
11.10 /** Specifies no Identity */
11.11 #define DEFAULT_IDENTITY NULL
11.12 @@ -357,6 +357,13 @@
11.13 const HandleSecurity *pSec,
11.14 const HandleAccess *pAccess,
11.15 HandleError *err) =0;
11.16 +
11.17 + /**
11.18 + * @brief Clones a handle, bypassing security checks.
11.19 + *
11.20 + * @return A new Handle_t, or 0 on failure.
11.21 + */
11.22 + virtual Handle_t FastCloneHandle(Handle_t hndl) =0;
11.23 };
11.24 }
11.25