core/logic/smn_players.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Aug 14 14:20:57 2013 -0400 (2013-08-14)
changeset 4008 490b01aa0683
parent 3872 4c93f74cae51
permissions -rw-r--r--
Updated some CS:GO gamedata.
     1 /**
     2  * vim: set ts=4 sw=4 tw=99 noet :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     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.
    11  * 
    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
    15  * details.
    16  *
    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/>.
    19  *
    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>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "common_logic.h"
    33 #include <IPluginSys.h>
    34 #include <IPlayerHelpers.h>
    35 #include <sh_string.h>
    36 #include <sh_list.h>
    37 #include "CellArray.h"
    38 #include "AutoHandleRooter.h"
    39 
    40 using namespace SourceHook;
    41 using namespace SourceMod;
    42 
    43 class PlayerLogicHelpers : 
    44 	public SMGlobalClass,
    45 	public IPluginsListener,
    46 	public ICommandTargetProcessor
    47 {
    48 	struct SimpleMultiTargetFilter
    49 	{
    50 		IPlugin *plugin;
    51 		SourceHook::String pattern;
    52 		IPluginFunction *fun;
    53 		SourceHook::String phrase;
    54 		bool phraseIsML;
    55 
    56 		SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
    57 		                        const char *phrase, bool phraseIsML)
    58 		  : plugin(plugin), pattern(pattern), fun(fun), phrase(phrase), phraseIsML(phraseIsML)
    59 		{
    60 		}
    61 	};
    62 
    63 	List<SimpleMultiTargetFilter *> simpleMultis;
    64 	bool filterEnabled;
    65 
    66 public:
    67 	void AddMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
    68 	                          const char *phrase, bool phraseIsML)
    69 	{
    70 		SimpleMultiTargetFilter *smtf = new SimpleMultiTargetFilter(plugin, pattern, fun, phrase,
    71 		                                                            phraseIsML);
    72 
    73 		simpleMultis.push_back(smtf);
    74 
    75 		if (!filterEnabled) {
    76 			playerhelpers->RegisterCommandTargetProcessor(this);
    77 			filterEnabled = true;
    78 		}
    79 	}
    80 
    81 	void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun)
    82 	{
    83 		List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
    84 
    85 		while (iter != simpleMultis.end()) {
    86 			if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) {
    87 				delete (*iter);
    88 				iter = simpleMultis.erase(iter);
    89 				break;
    90 			}
    91 			iter++;
    92 		}
    93 	}
    94 
    95 	PlayerLogicHelpers()
    96 	 : filterEnabled(false)
    97 	{
    98 	}
    99 
   100 public: //ICommandTargetProcessor
   101 	bool ProcessCommandTarget(cmd_target_info_t *info)
   102 	{
   103 		List<SimpleMultiTargetFilter *>::iterator iter;
   104 
   105 		for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) {
   106 			SimpleMultiTargetFilter *smtf = (*iter);
   107 			if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) {
   108 				CellArray *array = new CellArray(1);
   109 				HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
   110 				Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
   111 				AutoHandleCloner ahc(hndl, sec);
   112 				if (ahc.getClone() == BAD_HANDLE) {
   113 					smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
   114 					delete array;
   115 					return false;
   116 				}
   117 
   118 				smtf->fun->PushString(info->pattern);
   119 				smtf->fun->PushCell(ahc.getClone());
   120 				cell_t result = 0;
   121 				if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
   122 					return false;
   123 
   124 				IGamePlayer *pAdmin = info->admin
   125 				                      ? playerhelpers->GetGamePlayer(info->admin)
   126 				                      : NULL;
   127 
   128 				info->num_targets = 0;
   129 				for (size_t i = 0; i < array->size(); i++) {
   130 					cell_t client = *array->at(i);
   131 					IGamePlayer *pClient = playerhelpers->GetGamePlayer(client);
   132 					if (pClient == NULL || !pClient->IsConnected())
   133 						continue;
   134 					if (playerhelpers->FilterCommandTarget(pAdmin, pClient, info->flags) ==
   135 					    COMMAND_TARGET_VALID)
   136 					{
   137 						info->targets[info->num_targets++] = client;
   138 						if (info->num_targets >= unsigned(info->max_targets))
   139 							break;
   140 					}
   141 				}
   142 
   143 				info->reason = info->num_targets > 0
   144 				               ? COMMAND_TARGET_VALID
   145 				               : COMMAND_TARGET_EMPTY_FILTER;
   146 				if (info->num_targets) {
   147 					smcore.strncopy(info->target_name, smtf->phrase.c_str(), info->target_name_maxlength);
   148 					info->target_name_style = smtf->phraseIsML
   149 					                          ? COMMAND_TARGETNAME_ML
   150 					                          : COMMAND_TARGETNAME_RAW;
   151 				}
   152 
   153 				return true;
   154 			}
   155 		}
   156 
   157 		return false;
   158 	}
   159 
   160 public: //SMGlobalClass
   161 	void OnSourceModAllInitialized()
   162 	{
   163 		pluginsys->AddPluginsListener(this);
   164 	}
   165 
   166 	void OnSourceModShutdown()
   167 	{
   168 		pluginsys->RemovePluginsListener(this);
   169 		if (filterEnabled) {
   170 			playerhelpers->UnregisterCommandTargetProcessor(this);
   171 			filterEnabled = false;
   172 		}
   173 	}
   174 
   175 public: //IPluginsListener
   176 
   177 	void OnPluginDestroyed(IPlugin *plugin)
   178 	{
   179 		List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
   180 
   181 		while (iter != simpleMultis.end()) {
   182 			if ((*iter)->plugin != plugin) {
   183 				iter++;
   184 			} else {
   185 				delete (*iter);
   186 				iter = simpleMultis.erase(iter);
   187 			}
   188 		}
   189 	}
   190 } s_PlayerLogicHelpers;
   191 
   192 static cell_t
   193 AddMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
   194 {
   195 	IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
   196 	if (fun == NULL)
   197 		return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
   198 
   199 	char *pattern;
   200 	char *phrase;
   201 
   202 	ctx->LocalToString(params[1], &pattern);
   203 	ctx->LocalToString(params[3], &phrase);
   204 
   205 	bool phraseIsML = !!params[4];
   206 	IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
   207 
   208 	s_PlayerLogicHelpers.AddMultiTargetFilter(plugin, pattern, fun, phrase, phraseIsML);
   209 
   210 	return 1;
   211 }
   212 
   213 static cell_t
   214 RemoveMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
   215 {
   216 	IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
   217 	if (fun == NULL)
   218 		return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
   219 
   220 	char *pattern;
   221 
   222 	ctx->LocalToString(params[1], &pattern);
   223 
   224 	s_PlayerLogicHelpers.RemoveMultiTargetFilter(pattern, fun);
   225 
   226 	return 1;
   227 }
   228 
   229 REGISTER_NATIVES(playernatives)
   230 {
   231 	{"AddMultiTargetFilter",	AddMultiTargetFilter},
   232 	{"RemoveMultiTargetFilter",	RemoveMultiTargetFilter},
   233 	{NULL,						NULL}
   234 };
   235