dvander@2996: /**
dvander@2996: * vim: set ts=4 sw=4 tw=99 noet :
dvander@2996: * =============================================================================
dvander@2996: * SourceMod
dvander@2996: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
dvander@2996: * =============================================================================
dvander@2996: *
dvander@2996: * This program is free software; you can redistribute it and/or modify it under
dvander@2996: * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2996: * Free Software Foundation.
dvander@2996: *
dvander@2996: * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2996: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2996: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
dvander@2996: * details.
dvander@2996: *
dvander@2996: * You should have received a copy of the GNU General Public License along with
dvander@2996: * this program. If not, see .
dvander@2996: *
dvander@2996: * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2996: * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2996: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2996: * by the Valve Corporation. You must obey the GNU General Public License in
dvander@2996: * all respects for all other code used. Additionally, AlliedModders LLC grants
dvander@2996: * this exception to all derivative works. AlliedModders LLC defines further
dvander@2996: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2996: * or .
dvander@2996: *
dvander@2996: * Version: $Id$
dvander@2996: */
dvander@2996:
dvander@2996: #include "common_logic.h"
dvander@2996: #include
dvander@2996: #include
dvander@2996: #include
dvander@2996: #include
dvander@3872: #include "CellArray.h"
dvander@2996: #include "AutoHandleRooter.h"
dvander@2996:
dvander@2996: using namespace SourceHook;
dvander@2996: using namespace SourceMod;
dvander@2996:
dvander@2996: class PlayerLogicHelpers :
dvander@2996: public SMGlobalClass,
dvander@2996: public IPluginsListener,
dvander@2996: public ICommandTargetProcessor
dvander@2996: {
dvander@2996: struct SimpleMultiTargetFilter
dvander@2996: {
dvander@2996: IPlugin *plugin;
dvander@2996: SourceHook::String pattern;
dvander@2996: IPluginFunction *fun;
dvander@2996: SourceHook::String phrase;
dvander@2996: bool phraseIsML;
dvander@2996:
dvander@2996: SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
dvander@2996: const char *phrase, bool phraseIsML)
dvander@2996: : plugin(plugin), pattern(pattern), fun(fun), phrase(phrase), phraseIsML(phraseIsML)
dvander@2996: {
dvander@2996: }
dvander@2996: };
dvander@2996:
dvander@2996: List simpleMultis;
dvander@2996: bool filterEnabled;
dvander@2996:
dvander@2996: public:
dvander@2996: void AddMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
dvander@2996: const char *phrase, bool phraseIsML)
dvander@2996: {
dvander@2996: SimpleMultiTargetFilter *smtf = new SimpleMultiTargetFilter(plugin, pattern, fun, phrase,
dvander@2996: phraseIsML);
dvander@2996:
dvander@2996: simpleMultis.push_back(smtf);
dvander@2996:
dvander@2996: if (!filterEnabled) {
dvander@2996: playerhelpers->RegisterCommandTargetProcessor(this);
dvander@2996: filterEnabled = true;
dvander@2996: }
dvander@2996: }
dvander@2996:
dvander@2996: void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun)
dvander@2996: {
dvander@2996: List::iterator iter = simpleMultis.begin();
dvander@2996:
dvander@2996: while (iter != simpleMultis.end()) {
dvander@2996: if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) {
dvander@2996: delete (*iter);
dvander@2996: iter = simpleMultis.erase(iter);
dvander@2996: break;
dvander@2996: }
dvander@2996: iter++;
dvander@2996: }
dvander@2996: }
dvander@2996:
dvander@2996: PlayerLogicHelpers()
dvander@2996: : filterEnabled(false)
dvander@2996: {
dvander@2996: }
dvander@2996:
dvander@2996: public: //ICommandTargetProcessor
dvander@2996: bool ProcessCommandTarget(cmd_target_info_t *info)
dvander@2996: {
dvander@2996: List::iterator iter;
dvander@2996:
dvander@2996: for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) {
dvander@2996: SimpleMultiTargetFilter *smtf = (*iter);
dvander@2996: if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) {
dvander@2996: CellArray *array = new CellArray(1);
dvander@2996: HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
dvander@2996: Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
dvander@2996: AutoHandleCloner ahc(hndl, sec);
dvander@2996: if (ahc.getClone() == BAD_HANDLE) {
dvander@2996: smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
dvander@2996: delete array;
dvander@2996: return false;
dvander@2996: }
dvander@2996:
dvander@2996: smtf->fun->PushString(info->pattern);
dvander@2996: smtf->fun->PushCell(ahc.getClone());
dvander@2996: cell_t result = 0;
dvander@2996: if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
dvander@2996: return false;
dvander@2996:
dvander@2996: IGamePlayer *pAdmin = info->admin
dvander@2996: ? playerhelpers->GetGamePlayer(info->admin)
dvander@2996: : NULL;
dvander@2996:
dvander@2996: info->num_targets = 0;
dvander@2996: for (size_t i = 0; i < array->size(); i++) {
dvander@2996: cell_t client = *array->at(i);
dvander@2996: IGamePlayer *pClient = playerhelpers->GetGamePlayer(client);
dvander@2996: if (pClient == NULL || !pClient->IsConnected())
dvander@2996: continue;
dvander@2996: if (playerhelpers->FilterCommandTarget(pAdmin, pClient, info->flags) ==
dvander@2996: COMMAND_TARGET_VALID)
dvander@2996: {
dvander@2996: info->targets[info->num_targets++] = client;
dvander@2996: if (info->num_targets >= unsigned(info->max_targets))
dvander@2996: break;
dvander@2996: }
dvander@2996: }
dvander@2996:
dvander@2996: info->reason = info->num_targets > 0
dvander@2996: ? COMMAND_TARGET_VALID
dvander@2996: : COMMAND_TARGET_EMPTY_FILTER;
dvander@2996: if (info->num_targets) {
dvander@2996: smcore.strncopy(info->target_name, smtf->phrase.c_str(), info->target_name_maxlength);
dvander@2996: info->target_name_style = smtf->phraseIsML
dvander@2996: ? COMMAND_TARGETNAME_ML
dvander@2996: : COMMAND_TARGETNAME_RAW;
dvander@2996: }
dvander@2996:
dvander@2996: return true;
dvander@2996: }
dvander@2996: }
dvander@2996:
dvander@2996: return false;
dvander@2996: }
dvander@2996:
dvander@2996: public: //SMGlobalClass
dvander@2996: void OnSourceModAllInitialized()
dvander@2996: {
dvander@2996: pluginsys->AddPluginsListener(this);
dvander@2996: }
dvander@2996:
dvander@2996: void OnSourceModShutdown()
dvander@2996: {
dvander@2996: pluginsys->RemovePluginsListener(this);
dvander@2996: if (filterEnabled) {
dvander@2996: playerhelpers->UnregisterCommandTargetProcessor(this);
dvander@2996: filterEnabled = false;
dvander@2996: }
dvander@2996: }
dvander@2996:
dvander@2996: public: //IPluginsListener
dvander@2996:
dvander@2996: void OnPluginDestroyed(IPlugin *plugin)
dvander@2996: {
dvander@2996: List::iterator iter = simpleMultis.begin();
dvander@2996:
dvander@2996: while (iter != simpleMultis.end()) {
dvander@2996: if ((*iter)->plugin != plugin) {
dvander@2996: iter++;
dvander@2996: } else {
dvander@2996: delete (*iter);
dvander@2996: iter = simpleMultis.erase(iter);
dvander@2996: }
dvander@2996: }
dvander@2996: }
dvander@2996: } s_PlayerLogicHelpers;
dvander@2996:
dvander@2996: static cell_t
dvander@2996: AddMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
dvander@2996: {
dvander@2996: IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
dvander@2996: if (fun == NULL)
dvander@2996: return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
dvander@2996:
dvander@2996: char *pattern;
dvander@2996: char *phrase;
dvander@2996:
dvander@2996: ctx->LocalToString(params[1], &pattern);
dvander@2996: ctx->LocalToString(params[3], &phrase);
dvander@2996:
dvander@2996: bool phraseIsML = !!params[4];
dvander@2996: IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
dvander@2996:
dvander@2996: s_PlayerLogicHelpers.AddMultiTargetFilter(plugin, pattern, fun, phrase, phraseIsML);
dvander@2996:
dvander@2996: return 1;
dvander@2996: }
dvander@2996:
dvander@2996: static cell_t
dvander@2996: RemoveMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
dvander@2996: {
dvander@2996: IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
dvander@2996: if (fun == NULL)
dvander@2996: return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
dvander@2996:
dvander@2996: char *pattern;
dvander@2996:
dvander@2996: ctx->LocalToString(params[1], &pattern);
dvander@2996:
dvander@2996: s_PlayerLogicHelpers.RemoveMultiTargetFilter(pattern, fun);
dvander@2996:
dvander@2996: return 1;
dvander@2996: }
dvander@2996:
dvander@2996: REGISTER_NATIVES(playernatives)
dvander@2996: {
dvander@2996: {"AddMultiTargetFilter", AddMultiTargetFilter},
dvander@2996: {"RemoveMultiTargetFilter", RemoveMultiTargetFilter},
dvander@2996: {NULL, NULL}
dvander@2996: };
dvander@2996: