extensions/sdktools/outputnatives.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 22 09:49:27 2014 -0400 (2014-05-22)
changeset 4378 568f4497ef4a
parent 2746 8d68569b9648
permissions -rw-r--r--
Update CS:GO team score gamedata.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     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 "extension.h"
    33 #include "output.h"
    34 
    35 // HookSingleEntityOutput(ent, const String:output[], function, bool:once);
    36 cell_t HookSingleEntityOutput(IPluginContext *pContext, const cell_t *params)
    37 {
    38 	if (!g_OutputManager.IsEnabled())
    39 	{
    40 		return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
    41 	}
    42 
    43 	CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(params[1]);
    44 	if (!pEntity)
    45 	{
    46 		return pContext->ThrowNativeError("Invalid Entity index %i (%i)", gamehelpers->ReferenceToIndex(params[1]), params[1]);
    47 	}
    48 
    49 	const char *classname = g_OutputManager.GetEntityClassname(pEntity);
    50 
    51 	char *outputname;
    52 	pContext->LocalToString(params[2], &outputname);
    53 
    54 	OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true);
    55 
    56 	//Check for an existing identical hook
    57 	SourceHook::List<omg_hooks *>::iterator _iter;
    58 
    59 	omg_hooks *hook;
    60 
    61 	IPluginFunction *pFunction;
    62 	pFunction = pContext->GetFunctionById(params[3]);
    63 
    64 	for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
    65 	{
    66 		hook = (omg_hooks *)*_iter;
    67 		if (hook->pf == pFunction && hook->entity_ref == gamehelpers->EntityToReference(pEntity))
    68 		{
    69 			return 0;
    70 		}
    71 	}
    72 
    73 	hook = g_OutputManager.NewHook();
    74 
    75 	hook->entity_ref = gamehelpers->EntityToReference(pEntity);
    76 	hook->only_once= !!params[4];
    77 	hook->pf = pFunction;
    78 	hook->m_parent = pOutputName;
    79 	hook->in_use = false;
    80 	hook->delete_me = false;
    81 
    82 	pOutputName->hooks.push_back(hook);
    83 
    84 	g_OutputManager.OnHookAdded();
    85 
    86 	IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
    87 	SourceHook::List<omg_hooks *> *pList = NULL;
    88 
    89 	if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList)
    90 	{
    91 		pList = new SourceHook::List<omg_hooks *>;
    92 		pPlugin->SetProperty("OutputHookList", pList);
    93 	}
    94 
    95 	pList->push_back(hook);
    96 
    97 	return 1;
    98 }
    99 
   100 // HookEntityOutput(const String:classname[], const String:output[], function);
   101 cell_t HookEntityOutput(IPluginContext *pContext, const cell_t *params)
   102 {
   103 	if (!g_OutputManager.IsEnabled())
   104 	{
   105 		return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
   106 	}
   107 
   108 	//Find or create the base structures for this classname and the output
   109 	char *classname;
   110 	pContext->LocalToString(params[1], &classname);
   111 
   112 	char *outputname;
   113 	pContext->LocalToString(params[2], &outputname);
   114 
   115 	OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true);
   116 
   117 	//Check for an existing identical hook
   118 	SourceHook::List<omg_hooks *>::iterator _iter;
   119 
   120 	omg_hooks *hook;
   121 
   122 	IPluginFunction *pFunction;
   123 	pFunction = pContext->GetFunctionById(params[3]);
   124 
   125 	for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
   126 	{
   127 		hook = (omg_hooks *)*_iter;
   128 		if (hook->pf == pFunction && hook->entity_ref == -1)
   129 		{
   130 			//already hooked to this function...
   131 			//throw an error or just let them get away with stupidity?
   132 			// seems like poor coding if they dont know if something is hooked or not
   133 			return 0;
   134 		}
   135 	}
   136 
   137 	hook = g_OutputManager.NewHook();
   138 
   139 	hook->entity_ref = -1;
   140 	hook->pf = pFunction;
   141 	hook->m_parent = pOutputName;
   142 	hook->in_use = false;
   143 	hook->delete_me = false;
   144 
   145 	pOutputName->hooks.push_back(hook);
   146 
   147 	g_OutputManager.OnHookAdded();
   148 
   149 	IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
   150 	SourceHook::List<omg_hooks *> *pList = NULL;
   151 
   152 	if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList)
   153 	{
   154 		pList = new SourceHook::List<omg_hooks *>;
   155 		pPlugin->SetProperty("OutputHookList", pList);
   156 	}
   157 
   158 	pList->push_back(hook);
   159 
   160 	return 1;
   161 }
   162 
   163 // UnHookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback);
   164 cell_t UnHookEntityOutput(IPluginContext *pContext, const cell_t *params)
   165 {
   166 	if (!g_OutputManager.IsEnabled())
   167 	{
   168 		return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
   169 	}
   170 
   171 	char *classname;
   172 	pContext->LocalToString(params[1], &classname);
   173 
   174 	char *outputname;
   175 	pContext->LocalToString(params[2], &outputname);
   176 
   177 	OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, false);
   178 
   179 	if (!pOutputName)
   180 	{
   181 		return 0;
   182 	}
   183 
   184 	//Check for an existing identical hook
   185 	SourceHook::List<omg_hooks *>::iterator _iter;
   186 
   187 	omg_hooks *hook;
   188 
   189 	IPluginFunction *pFunction;
   190 	pFunction = pContext->GetFunctionById(params[3]);
   191 
   192 	for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
   193 	{
   194 		hook = (omg_hooks *)*_iter;
   195 		if (hook->pf == pFunction && hook->entity_ref == -1)
   196 		{
   197 			// remove this hook.
   198 			if (hook->in_use)
   199 			{
   200 				hook->delete_me = true;
   201 				return 1;
   202 			}
   203 
   204 			pOutputName->hooks.erase(_iter);
   205 			g_OutputManager.CleanUpHook(hook);
   206 
   207 			return 1;
   208 		}
   209 	}
   210 
   211 	return 0;
   212 }
   213 
   214 // UnHookSingleEntityOutput(entity, const String:output[], EntityOutput:callback);
   215 cell_t UnHookSingleEntityOutput(IPluginContext *pContext, const cell_t *params)
   216 {
   217 	if (!g_OutputManager.IsEnabled())
   218 	{
   219 		return pContext->ThrowNativeError("Entity Outputs are disabled - See error logs for details");
   220 	}
   221 
   222 	// Find the classname of the entity and lookup the classname and output structures
   223 	CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(params[1]);
   224 	if (!pEntity)
   225 	{
   226 		return pContext->ThrowNativeError("Invalid Entity index %i (%i)", gamehelpers->ReferenceToIndex(params[1]), params[1]);
   227 	}
   228 
   229 	const char *classname = g_OutputManager.GetEntityClassname(pEntity);
   230 
   231 	char *outputname;
   232 	pContext->LocalToString(params[2], &outputname);
   233 
   234 	OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, false);
   235 
   236 	if (!pOutputName)
   237 	{
   238 		return 0;
   239 	}
   240 
   241 	//Check for an existing identical hook
   242 	SourceHook::List<omg_hooks *>::iterator _iter;
   243 
   244 	omg_hooks *hook;
   245 
   246 	IPluginFunction *pFunction;
   247 	pFunction = pContext->GetFunctionById(params[3]);
   248 
   249 	for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++)
   250 	{
   251 		hook = (omg_hooks *)*_iter;
   252 		/* We're not serial checking and just removing by index here - This was always allowed so is left for bcompat */
   253 		if (hook->pf == pFunction && gamehelpers->ReferenceToIndex(hook->entity_ref) == gamehelpers->ReferenceToIndex(params[1]))
   254 		{
   255 			// remove this hook.
   256 			if (hook->in_use)
   257 			{
   258 				hook->delete_me = true;
   259 				return 1;
   260 			}
   261 
   262 			pOutputName->hooks.erase(_iter);
   263 			g_OutputManager.CleanUpHook(hook);
   264 
   265 			return 1;
   266 		}
   267 	}
   268 
   269 	return 0;
   270 }
   271 
   272 sp_nativeinfo_t g_EntOutputNatives[] =
   273 {
   274 	{"HookEntityOutput",			HookEntityOutput},
   275 	{"UnhookEntityOutput",			UnHookEntityOutput},
   276 	{"HookSingleEntityOutput",		HookSingleEntityOutput},
   277 	{"UnhookSingleEntityOutput",	UnHookSingleEntityOutput},
   278 	{NULL,							NULL},
   279 };