extensions/sdktools/extension.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun Dec 02 01:51:48 2007 +0000 (2007-12-02)
changeset 1735 d6966e3316e9
parent 1644 7033022af10d
child 1757 455a2ea38c67
permissions -rw-r--r--
added amb861, sounds can be hooked now
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     5  * Copyright (C) 2004-2007 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 "vcallbuilder.h"
    34 #include "vnatives.h"
    35 #include "vhelpers.h"
    36 #include "vglobals.h"
    37 #include "tempents.h"
    38 #include "vsound.h"
    39 
    40 #if defined ORANGEBOX_BUILD
    41 	#define SDKTOOLS_GAME_FILE		"sdktools.games.ep2"
    42 #else
    43 	#define SDKTOOLS_GAME_FILE		"sdktools.games"
    44 #endif
    45 
    46 /**
    47  * @file extension.cpp
    48  * @brief Implements SDK Tools extension code.
    49  */
    50 
    51 SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
    52 SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
    53 
    54 SDKTools g_SdkTools;		/**< Global singleton for extension's main interface */
    55 IServerGameEnts *gameents = NULL;
    56 IEngineTrace *enginetrace = NULL;
    57 IEngineSound *engsound = NULL;
    58 INetworkStringTableContainer *netstringtables = NULL;
    59 IServerPluginHelpers *pluginhelpers = NULL;
    60 IBinTools *g_pBinTools = NULL;
    61 IGameConfig *g_pGameConf = NULL;
    62 IGameHelpers *g_pGameHelpers = NULL;
    63 IServerGameClients *serverClients = NULL;
    64 IVoiceServer *voiceserver = NULL;
    65 IPlayerInfoManager *playerinfomngr = NULL;
    66 ICvar *icvar = NULL;
    67 SourceHook::CallClass<IVEngineServer> *enginePatch = NULL;
    68 SourceHook::CallClass<IEngineSound> *enginesoundPatch = NULL;
    69 HandleType_t g_CallHandle = 0;
    70 HandleType_t g_TraceHandle = 0;
    71 
    72 SMEXT_LINK(&g_SdkTools);
    73 
    74 extern sp_nativeinfo_t g_CallNatives[];
    75 extern sp_nativeinfo_t g_TENatives[];
    76 extern sp_nativeinfo_t g_TRNatives[];
    77 extern sp_nativeinfo_t g_StringTableNatives[];
    78 extern sp_nativeinfo_t g_VoiceNatives[];
    79 extern sp_nativeinfo_t g_EntInputNatives[];
    80 extern sp_nativeinfo_t g_TeamNatives[];
    81 
    82 bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
    83 {
    84 	sharesys->AddDependency(myself, "bintools.ext", true, true);
    85 	sharesys->AddNatives(myself, g_CallNatives);
    86 	sharesys->AddNatives(myself, g_Natives);
    87 	sharesys->AddNatives(myself, g_TENatives);
    88 	sharesys->AddNatives(myself, g_SoundNatives);
    89 	sharesys->AddNatives(myself, g_TRNatives);
    90 	sharesys->AddNatives(myself, g_StringTableNatives);
    91 	sharesys->AddNatives(myself, g_VoiceNatives);
    92 	sharesys->AddNatives(myself, g_EntInputNatives);
    93 	sharesys->AddNatives(myself, g_TeamNatives);
    94 
    95 	SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
    96 
    97 	if (!gameconfs->LoadGameConfigFile(SDKTOOLS_GAME_FILE, &g_pGameConf, error, maxlength))
    98 	{
    99 		return false;
   100 	}
   101 
   102 	playerhelpers->AddClientListener(&g_SdkTools);
   103 	g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
   104 	g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
   105 
   106 #if defined ORANGEBOX_BUILD
   107 	g_pCVar = icvar;
   108 #endif
   109 	CONVAR_REGISTER(this);
   110 
   111 	SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
   112 	SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
   113 
   114 	playerhelpers->RegisterCommandTargetProcessor(this);
   115 
   116 	MathLib_Init(2.2f, 2.2f, 0.0f, 2);
   117 
   118 	return true;
   119 }
   120 
   121 void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
   122 {
   123 	if (type == g_CallHandle)
   124 	{
   125 		ValveCall *v = (ValveCall *)object;
   126 		delete v;
   127 	}
   128 	else if (type == g_TraceHandle)
   129 	{
   130 		trace_t *tr = (trace_t *)object;
   131 		delete tr;
   132 	}
   133 }
   134 
   135 void SDKTools::SDK_OnUnload()
   136 {
   137 	SourceHook::List<ValveCall *>::iterator iter;
   138 	for (iter = g_RegCalls.begin();
   139 		 iter != g_RegCalls.end();
   140 		 iter++)
   141 	{
   142 		delete (*iter);
   143 	}
   144 	g_RegCalls.clear();
   145 	ShutdownHelpers();
   146 
   147 	if (g_pAcceptInput)
   148 	{
   149 		g_pAcceptInput->Destroy();
   150 		g_pAcceptInput = NULL;
   151 	}
   152 
   153 	g_TEManager.Shutdown();
   154 	s_TempEntHooks.Shutdown();
   155 	s_SoundHooks.Shutdown();
   156 
   157 	gameconfs->CloseGameConfigFile(g_pGameConf);
   158 	playerhelpers->RemoveClientListener(&g_SdkTools);
   159 	playerhelpers->UnregisterCommandTargetProcessor(this);
   160 
   161 	SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
   162 	SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
   163 
   164 	if (enginePatch)
   165 	{
   166 		SH_RELEASE_CALLCLASS(enginePatch);
   167 		enginePatch = NULL;
   168 	}
   169 	if (enginesoundPatch)
   170 	{
   171 		SH_RELEASE_CALLCLASS(enginesoundPatch);
   172 		enginesoundPatch = NULL;
   173 	}
   174 }
   175 
   176 bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
   177 {
   178 	GET_V_IFACE_ANY(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
   179 	GET_V_IFACE_ANY(GetEngineFactory, engsound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
   180 	GET_V_IFACE_ANY(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER);
   181 	GET_V_IFACE_ANY(GetEngineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER);
   182 	GET_V_IFACE_ANY(GetEngineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
   183 	GET_V_IFACE_ANY(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
   184 	GET_V_IFACE_ANY(GetEngineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER);
   185 	GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER);
   186 	GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
   187 
   188 	enginePatch = SH_GET_CALLCLASS(engine);
   189 	enginesoundPatch = SH_GET_CALLCLASS(engsound);
   190 
   191 	return true;
   192 }
   193 
   194 void SDKTools::SDK_OnAllLoaded()
   195 {
   196 	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
   197 
   198 	g_TEManager.Initialize();
   199 	s_TempEntHooks.Initialize();
   200 	s_SoundHooks.Initialize();
   201 	InitializeValveGlobals();
   202 }
   203 
   204 bool SDKTools::QueryRunning(char *error, size_t maxlength)
   205 {
   206 	SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
   207 
   208 	return true;
   209 }
   210 
   211 bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface)
   212 {
   213 	if (pInterface == g_pBinTools)
   214 	{
   215 		return false;
   216 	}
   217 
   218 	return IExtensionInterface::QueryInterfaceDrop(pInterface);
   219 }
   220 
   221 void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface)
   222 {
   223 	SourceHook::List<ValveCall *>::iterator iter;
   224 	for (iter = g_RegCalls.begin();
   225 		iter != g_RegCalls.end();
   226 		iter++)
   227 	{
   228 		delete (*iter);
   229 	}
   230 	g_RegCalls.clear();
   231 	ShutdownHelpers();
   232 
   233 	g_TEManager.Shutdown();
   234 	s_TempEntHooks.Shutdown();
   235 
   236 	if (g_pAcceptInput)
   237 	{
   238 		g_pAcceptInput->Destroy();
   239 		g_pAcceptInput = NULL;
   240 	}
   241 }
   242 
   243 bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar)
   244 {
   245 #if defined METAMOD_PLAPI_VERSION
   246 	return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
   247 #else
   248 	return g_SMAPI->RegisterConCmdBase(g_PLAPI, pVar);
   249 #endif
   250 }
   251 
   252 bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
   253 {
   254 	const char *name;
   255 	char key[32];
   256 	int count, n = 1;
   257 
   258 	if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount")))
   259 	{
   260 		RETURN_META_VALUE(MRES_IGNORED, true);
   261 	}
   262 
   263 	count = atoi(name);
   264 
   265 	while (n <= count)
   266 	{
   267 		snprintf(key, sizeof(key), "SlapSound%d", n);
   268 		if ((name=g_pGameConf->GetKeyValue(key)))
   269 		{
   270 			engsound->PrecacheSound(name, true);
   271 		}
   272 		n++;
   273 	}
   274 
   275 	RETURN_META_VALUE(MRES_IGNORED, true);
   276 }
   277 
   278 bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
   279 {
   280 	if (strcmp(info->pattern, "@aim") != 0)
   281 	{
   282 		return false;
   283 	}
   284 
   285 	IGamePlayer *pAdmin = info->admin ? playerhelpers->GetGamePlayer(info->admin) : NULL;
   286 
   287 	/* The server can't aim, of course. */
   288 	if (pAdmin == NULL)
   289 	{
   290 		return false;
   291 	}
   292 
   293 	int player_index;
   294 	if ((player_index = GetClientAimTarget(pAdmin->GetEdict(), true)) < 1)
   295 	{
   296 		return false;
   297 	}
   298 
   299 	IGamePlayer *pTarget = playerhelpers->GetGamePlayer(info->admin);
   300 
   301 	info->targets[0] = player_index;
   302 	info->num_targets = 1;
   303 	info->reason = COMMAND_TARGET_VALID;
   304 	info->target_name_style = COMMAND_TARGETNAME_RAW;
   305 	snprintf(info->target_name, info->target_name_maxlength, "%s", pTarget->GetName());
   306 
   307 	return true;
   308 }