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: