Added ProcessTargetString simple filter API (bug 4404, r=ds).
This commit is contained in:
parent
fb28f4bcd0
commit
28217f10cb
@ -31,6 +31,7 @@ files = [
|
||||
'Profiler.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'sm_crc32.cpp'
|
||||
]
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
|
92
core/logic/AutoHandleRooter.h
Normal file
92
core/logic/AutoHandleRooter.h
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
|
||||
#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IHandleSys.h>
|
||||
|
||||
class AutoHandleRooter
|
||||
{
|
||||
public:
|
||||
AutoHandleRooter(Handle_t hndl)
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
this->hndl = handlesys->FastCloneHandle(hndl);
|
||||
else
|
||||
this->hndl = BAD_HANDLE;
|
||||
}
|
||||
|
||||
~AutoHandleRooter()
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
{
|
||||
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
|
||||
handlesys->FreeHandle(hndl, &sec);
|
||||
}
|
||||
}
|
||||
|
||||
Handle_t getHandle()
|
||||
{
|
||||
return hndl;
|
||||
}
|
||||
private:
|
||||
Handle_t hndl;
|
||||
};
|
||||
|
||||
class AutoHandleCloner
|
||||
{
|
||||
Handle_t original;
|
||||
HandleSecurity sec;
|
||||
AutoHandleRooter ahr;
|
||||
public:
|
||||
AutoHandleCloner(Handle_t original, HandleSecurity sec)
|
||||
: original(original), sec(sec), ahr(original)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoHandleCloner()
|
||||
{
|
||||
if (original != BAD_HANDLE)
|
||||
{
|
||||
handlesys->FreeHandle(original, &sec);
|
||||
}
|
||||
}
|
||||
|
||||
Handle_t getClone()
|
||||
{
|
||||
return ahr.getHandle();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ */
|
||||
|
@ -27,7 +27,8 @@ OBJECTS = \
|
||||
Profiler.cpp \
|
||||
smn_functions.cpp \
|
||||
sm_crc32.cpp \
|
||||
smn_timers.cpp
|
||||
smn_timers.cpp \
|
||||
smn_players.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
|
@ -52,6 +52,7 @@ IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
ITimerSystem *timersys;
|
||||
ServerGlobals serverGlobals;
|
||||
IPlayerManager *playerhelpers;
|
||||
|
||||
static sm_logic_t logic =
|
||||
{
|
||||
@ -79,6 +80,7 @@ static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
pluginsys = core->pluginsys;
|
||||
forwardsys = core->forwardsys;
|
||||
timersys = core->timersys;
|
||||
playerhelpers = core->playerhelpers;
|
||||
}
|
||||
|
||||
PLATFORM_EXTERN_C ITextParsers *get_textparsers()
|
||||
|
@ -49,6 +49,7 @@ extern IPluginManager *pluginsys;
|
||||
extern IForwardManager *forwardsys;
|
||||
extern ITimerSystem *timersys;
|
||||
extern ServerGlobals serverGlobals;
|
||||
extern IPlayerManager *playerhelpers;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
||||
|
||||
|
@ -42,7 +42,7 @@ using namespace SourceMod;
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 4)
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 5)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
@ -64,6 +64,7 @@ namespace SourceMod
|
||||
class IPluginManager;
|
||||
class IForwardManager;
|
||||
class ITimerSystem;
|
||||
class IPlayerManager;
|
||||
}
|
||||
|
||||
class IVEngineServer;
|
||||
@ -89,6 +90,7 @@ struct sm_core_t
|
||||
IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
ITimerSystem *timersys;
|
||||
IPlayerManager *playerhelpers;
|
||||
/* Functions */
|
||||
void (*AddNatives)(sp_nativeinfo_t* nlist);
|
||||
ConVar * (*FindConVar)(const char*);
|
||||
|
235
core/logic/smn_players.cpp
Normal file
235
core/logic/smn_players.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IPluginSys.h>
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
#include "AutoHandleRooter.h"
|
||||
#include "CellArray.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
class PlayerLogicHelpers :
|
||||
public SMGlobalClass,
|
||||
public IPluginsListener,
|
||||
public ICommandTargetProcessor
|
||||
{
|
||||
struct SimpleMultiTargetFilter
|
||||
{
|
||||
IPlugin *plugin;
|
||||
SourceHook::String pattern;
|
||||
IPluginFunction *fun;
|
||||
SourceHook::String phrase;
|
||||
bool phraseIsML;
|
||||
|
||||
SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
|
||||
const char *phrase, bool phraseIsML)
|
||||
: plugin(plugin), pattern(pattern), fun(fun), phrase(phrase), phraseIsML(phraseIsML)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
List<SimpleMultiTargetFilter *> simpleMultis;
|
||||
bool filterEnabled;
|
||||
|
||||
public:
|
||||
void AddMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
|
||||
const char *phrase, bool phraseIsML)
|
||||
{
|
||||
SimpleMultiTargetFilter *smtf = new SimpleMultiTargetFilter(plugin, pattern, fun, phrase,
|
||||
phraseIsML);
|
||||
|
||||
simpleMultis.push_back(smtf);
|
||||
|
||||
if (!filterEnabled) {
|
||||
playerhelpers->RegisterCommandTargetProcessor(this);
|
||||
filterEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun)
|
||||
{
|
||||
List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
|
||||
|
||||
while (iter != simpleMultis.end()) {
|
||||
if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) {
|
||||
delete (*iter);
|
||||
iter = simpleMultis.erase(iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerLogicHelpers()
|
||||
: filterEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
public: //ICommandTargetProcessor
|
||||
bool ProcessCommandTarget(cmd_target_info_t *info)
|
||||
{
|
||||
List<SimpleMultiTargetFilter *>::iterator iter;
|
||||
|
||||
for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) {
|
||||
SimpleMultiTargetFilter *smtf = (*iter);
|
||||
if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) {
|
||||
CellArray *array = new CellArray(1);
|
||||
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
|
||||
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
|
||||
AutoHandleCloner ahc(hndl, sec);
|
||||
if (ahc.getClone() == BAD_HANDLE) {
|
||||
smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
|
||||
delete array;
|
||||
return false;
|
||||
}
|
||||
|
||||
smtf->fun->PushString(info->pattern);
|
||||
smtf->fun->PushCell(ahc.getClone());
|
||||
cell_t result = 0;
|
||||
if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
|
||||
return false;
|
||||
|
||||
IGamePlayer *pAdmin = info->admin
|
||||
? playerhelpers->GetGamePlayer(info->admin)
|
||||
: NULL;
|
||||
|
||||
info->num_targets = 0;
|
||||
for (size_t i = 0; i < array->size(); i++) {
|
||||
cell_t client = *array->at(i);
|
||||
IGamePlayer *pClient = playerhelpers->GetGamePlayer(client);
|
||||
if (pClient == NULL || !pClient->IsConnected())
|
||||
continue;
|
||||
if (playerhelpers->FilterCommandTarget(pAdmin, pClient, info->flags) ==
|
||||
COMMAND_TARGET_VALID)
|
||||
{
|
||||
info->targets[info->num_targets++] = client;
|
||||
if (info->num_targets >= unsigned(info->max_targets))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
info->reason = info->num_targets > 0
|
||||
? COMMAND_TARGET_VALID
|
||||
: COMMAND_TARGET_EMPTY_FILTER;
|
||||
if (info->num_targets) {
|
||||
smcore.strncopy(info->target_name, smtf->phrase.c_str(), info->target_name_maxlength);
|
||||
info->target_name_style = smtf->phraseIsML
|
||||
? COMMAND_TARGETNAME_ML
|
||||
: COMMAND_TARGETNAME_RAW;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
pluginsys->AddPluginsListener(this);
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
pluginsys->RemovePluginsListener(this);
|
||||
if (filterEnabled) {
|
||||
playerhelpers->UnregisterCommandTargetProcessor(this);
|
||||
filterEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public: //IPluginsListener
|
||||
|
||||
void OnPluginDestroyed(IPlugin *plugin)
|
||||
{
|
||||
List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
|
||||
|
||||
while (iter != simpleMultis.end()) {
|
||||
if ((*iter)->plugin != plugin) {
|
||||
iter++;
|
||||
} else {
|
||||
delete (*iter);
|
||||
iter = simpleMultis.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
} s_PlayerLogicHelpers;
|
||||
|
||||
static cell_t
|
||||
AddMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
|
||||
if (fun == NULL)
|
||||
return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
|
||||
char *pattern;
|
||||
char *phrase;
|
||||
|
||||
ctx->LocalToString(params[1], &pattern);
|
||||
ctx->LocalToString(params[3], &phrase);
|
||||
|
||||
bool phraseIsML = !!params[4];
|
||||
IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
|
||||
|
||||
s_PlayerLogicHelpers.AddMultiTargetFilter(plugin, pattern, fun, phrase, phraseIsML);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t
|
||||
RemoveMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
|
||||
{
|
||||
IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
|
||||
if (fun == NULL)
|
||||
return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
|
||||
|
||||
char *pattern;
|
||||
|
||||
ctx->LocalToString(params[1], &pattern);
|
||||
|
||||
s_PlayerLogicHelpers.RemoveMultiTargetFilter(pattern, fun);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(playernatives)
|
||||
{
|
||||
{"AddMultiTargetFilter", AddMultiTargetFilter},
|
||||
{"RemoveMultiTargetFilter", RemoveMultiTargetFilter},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "TimerSys.h"
|
||||
#include "logic_bridge.h"
|
||||
#include "DebugReporter.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
static ILibrary *g_pLogic = NULL;
|
||||
static LogicInitFunction logic_init_fn;
|
||||
@ -113,6 +114,7 @@ static sm_core_t core_bridge =
|
||||
&g_PluginSys,
|
||||
&g_Forwards,
|
||||
&g_Timers,
|
||||
&g_Players,
|
||||
/* Functions */
|
||||
add_natives,
|
||||
find_convar,
|
||||
|
@ -132,3 +132,34 @@ stock ReplyToTargetError(client, reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds clients to a multi-target filter.
|
||||
*
|
||||
* @param pattern Pattern name.
|
||||
* @param clients Array to fill with unique, valid client indexes.
|
||||
* @return True if pattern was recognized, false otherwise.
|
||||
*/
|
||||
functag public bool:MultiTargetFilter(const String:pattern[], Handle:clients);
|
||||
|
||||
/**
|
||||
* Adds a multi-target filter function for ProcessTargetString().
|
||||
*
|
||||
* @param pattern Pattern to match (case sensitive).
|
||||
* @param filter Filter function.
|
||||
* @param phrase Descriptive phrase to display on successful match.
|
||||
* @param phraseIsML True if phrase is multi-lingual, false otherwise.
|
||||
* @noreturn
|
||||
*/
|
||||
native AddMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter,
|
||||
const String:phrase[], bool:phraseIsML);
|
||||
|
||||
/**
|
||||
* Removes a multi-target filter function from ProcessTargetString().
|
||||
*
|
||||
* @param pattern Pattern to match (case sensitive).
|
||||
* @param filter Filter function.
|
||||
* @noreturn
|
||||
*/
|
||||
native RemoveMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter);
|
||||
|
||||
|
26
plugins/testsuite/ptstest.sp
Normal file
26
plugins/testsuite/ptstest.sp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <sourcemod>
|
||||
|
||||
public Plugin:myinfo =
|
||||
{
|
||||
name = "Test target filters",
|
||||
author = "AlliedModders LLC",
|
||||
description = "Tests target filters",
|
||||
version = "1.0.0.0",
|
||||
url = "http://www.sourcemod.net/"
|
||||
};
|
||||
|
||||
public OnPluginStart()
|
||||
{
|
||||
AddMultiTargetFilter("@crab", filter, "all players", true)
|
||||
}
|
||||
|
||||
public bool:filter(const String:pattern[], Handle:clients)
|
||||
{
|
||||
for (new i = 1; i <= MaxClients; i++) {
|
||||
if (IsPlayerInGame(i))
|
||||
PushArrayCell(clients, i)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
||||
#include <sp_vm_types.h>
|
||||
|
||||
#define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys"
|
||||
#define SMINTERFACE_HANDLESYSTEM_VERSION 3
|
||||
#define SMINTERFACE_HANDLESYSTEM_VERSION 4
|
||||
|
||||
/** Specifies no Identity */
|
||||
#define DEFAULT_IDENTITY NULL
|
||||
@ -357,6 +357,13 @@ namespace SourceMod
|
||||
const HandleSecurity *pSec,
|
||||
const HandleAccess *pAccess,
|
||||
HandleError *err) =0;
|
||||
|
||||
/**
|
||||
* @brief Clones a handle, bypassing security checks.
|
||||
*
|
||||
* @return A new Handle_t, or 0 on failure.
|
||||
*/
|
||||
virtual Handle_t FastCloneHandle(Handle_t hndl) =0;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user