extensions/sdktools/extension.cpp
author Kyle Sanderson <kyle.leet@gmail.com>
Sat Mar 16 22:15:25 2013 -0400 (2013-03-16)
changeset 3819 d17aed3d46bf
parent 3816 31650bb3c7e8
child 3854 8abb0924497b
permissions -rw-r--r--
Replace usages of deprecated Sourcehook Add/Remove macros (bug 5631, r=dvander).
ds@783
     1
/**
ds@783
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1233
     4
 * SourceMod SDKTools Extension
fyrenmoo@3089
     5
 * Copyright (C) 2004-2010 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
ds@783
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1233
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1233
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1233
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
ds@783
    28
 *
ds@783
    29
 * Version: $Id$
ds@783
    30
 */
ds@783
    31
dvander@2783
    32
#include <sourcemod_version.h>
ds@783
    33
#include "extension.h"
ds@2400
    34
#include <compat_wrappers.h>
dvander@950
    35
#include "vcallbuilder.h"
dvander@954
    36
#include "vnatives.h"
dvander@1169
    37
#include "vhelpers.h"
ds@1240
    38
#include "vglobals.h"
faluco@1031
    39
#include "tempents.h"
faluco@1735
    40
#include "vsound.h"
pred@1958
    41
#include "output.h"
pred@2711
    42
#include "hooks.h"
skamonkey@3333
    43
#include "gamerulesnatives.h"
dvander@2503
    44
#include <ISDKTools.h>
bluebriansimon@3339
    45
#include "clientnatives.h"
skamonkey@3816
    46
#include "teamnatives.h"
ds@783
    47
/**
ds@783
    48
 * @file extension.cpp
ds@995
    49
 * @brief Implements SDK Tools extension code.
ds@783
    50
 */
ds@783
    51
faluco@1262
    52
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
faluco@1262
    53
ds@783
    54
SDKTools g_SdkTools;		/**< Global singleton for extension's main interface */
ds@783
    55
IServerGameEnts *gameents = NULL;
faluco@1075
    56
IEngineTrace *enginetrace = NULL;
ds@1114
    57
IEngineSound *engsound = NULL;
ds@1114
    58
INetworkStringTableContainer *netstringtables = NULL;
dvander@1169
    59
IServerPluginHelpers *pluginhelpers = NULL;
ds@783
    60
IBinTools *g_pBinTools = NULL;
dvander@950
    61
IGameConfig *g_pGameConf = NULL;
faluco@1031
    62
IGameHelpers *g_pGameHelpers = NULL;
faluco@1219
    63
IServerGameClients *serverClients = NULL;
ds@1240
    64
IVoiceServer *voiceserver = NULL;
teame06@1239
    65
IPlayerInfoManager *playerinfomngr = NULL;
faluco@1560
    66
ICvar *icvar = NULL;
faluco@1769
    67
IServer *iserver = NULL;
ds@2400
    68
CGlobalVars *gpGlobals;
skamonkey@3280
    69
skamonkey@3280
    70
#if SOURCE_ENGINE >= SE_ORANGEBOX
skamonkey@3280
    71
IServerTools *servertools = NULL;
skamonkey@3280
    72
#endif
skamonkey@3280
    73
faluco@1735
    74
SourceHook::CallClass<IVEngineServer> *enginePatch = NULL;
faluco@1735
    75
SourceHook::CallClass<IEngineSound> *enginesoundPatch = NULL;
dvander@950
    76
HandleType_t g_CallHandle = 0;
faluco@1075
    77
HandleType_t g_TraceHandle = 0;
dvander@2503
    78
ISDKTools *g_pSDKTools;
ds@783
    79
ds@783
    80
SMEXT_LINK(&g_SdkTools);
ds@783
    81
dvander@950
    82
extern sp_nativeinfo_t g_CallNatives[];
faluco@1031
    83
extern sp_nativeinfo_t g_TENatives[];
faluco@1075
    84
extern sp_nativeinfo_t g_TRNatives[];
ds@1114
    85
extern sp_nativeinfo_t g_StringTableNatives[];
teame06@1235
    86
extern sp_nativeinfo_t g_VoiceNatives[];
faluco@1498
    87
extern sp_nativeinfo_t g_EntInputNatives[];
faluco@1613
    88
extern sp_nativeinfo_t g_TeamNatives[];
skamonkey@3333
    89
extern sp_nativeinfo_t g_GameRulesNatives[];
bluebriansimon@3339
    90
extern sp_nativeinfo_t g_ClientNatives[];
dvander@950
    91
dvander@2503
    92
static void InitSDKToolsAPI();
dvander@2503
    93
ds@783
    94
bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
ds@783
    95
{
dvander@2306
    96
	HandleError err;
dvander@2306
    97
dvander@2529
    98
	if (!gameconfs->LoadGameConfigFile("sdktools.games", &g_pGameConf, error, maxlength))
pred@2124
    99
	{
pred@2124
   100
		return false;
pred@2124
   101
	}
pred@2124
   102
dvander@950
   103
	sharesys->AddDependency(myself, "bintools.ext", true, true);
dvander@950
   104
	sharesys->AddNatives(myself, g_CallNatives);
dvander@954
   105
	sharesys->AddNatives(myself, g_Natives);
faluco@1031
   106
	sharesys->AddNatives(myself, g_TENatives);
dvander@1047
   107
	sharesys->AddNatives(myself, g_SoundNatives);
faluco@1075
   108
	sharesys->AddNatives(myself, g_TRNatives);
ds@1114
   109
	sharesys->AddNatives(myself, g_StringTableNatives);
teame06@1235
   110
	sharesys->AddNatives(myself, g_VoiceNatives);
faluco@1498
   111
	sharesys->AddNatives(myself, g_EntInputNatives);
faluco@1613
   112
	sharesys->AddNatives(myself, g_TeamNatives);
pred@1958
   113
	sharesys->AddNatives(myself, g_EntOutputNatives);
skamonkey@3333
   114
	sharesys->AddNatives(myself, g_GameRulesNatives);
bluebriansimon@3339
   115
	sharesys->AddNatives(myself, g_ClientNatives);
faluco@1031
   116
faluco@1031
   117
	SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
ds@783
   118
teame06@1235
   119
	playerhelpers->AddClientListener(&g_SdkTools);
dvander@2306
   120
	g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), &err);
dvander@2306
   121
	if (g_CallHandle == 0)
dvander@2306
   122
	{
dvander@2306
   123
		snprintf(error, maxlength, "Could not create call handle type (err: %d)", err);	
dvander@2306
   124
		return false;
dvander@2306
   125
	}
pred@2108
   126
pred@2108
   127
	TypeAccess TraceAccess;
pred@2108
   128
	handlesys->InitAccessDefaults(&TraceAccess, NULL);
pred@2116
   129
	TraceAccess.ident = myself->GetIdentity();
pred@2108
   130
	TraceAccess.access[HTypeAccess_Create] = true;
pred@2116
   131
	TraceAccess.access[HTypeAccess_Inherit] = true;
dvander@2306
   132
	g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, &TraceAccess, NULL, myself->GetIdentity(), &err);
dvander@2306
   133
	if (g_TraceHandle == 0)
dvander@2306
   134
	{
dvander@2306
   135
		handlesys->RemoveType(g_CallHandle, myself->GetIdentity());
dvander@2306
   136
		g_CallHandle = 0;
dvander@2306
   137
		snprintf(error, maxlength, "Could not create traceray handle type (err: %d)", err);
dvander@2306
   138
		return false;
dvander@2306
   139
	}
ds@783
   140
ds@2400
   141
#if SOURCE_ENGINE >= SE_ORANGEBOX
faluco@1560
   142
	g_pCVar = icvar;
faluco@1560
   143
#endif
faluco@1560
   144
	CONVAR_REGISTER(this);
dvander@1052
   145
kyle@3819
   146
	SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SDKTools::LevelInit), true);
faluco@1262
   147
dvander@1628
   148
	playerhelpers->RegisterCommandTargetProcessor(this);
dvander@1628
   149
dvander@1611
   150
	MathLib_Init(2.2f, 2.2f, 0.0f, 2);
dvander@1611
   151
pred@1958
   152
	spengine = g_pSM->GetScriptingEngine();
pred@1958
   153
pred@1958
   154
	plsys->AddPluginsListener(&g_OutputManager);
pred@1958
   155
fyrenmoo@3089
   156
	CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
pred@1958
   157
	g_OutputManager.Init();
pred@1958
   158
dvander@2044
   159
	VoiceInit();
dvander@2044
   160
dvander@2503
   161
	GetIServer();
dvander@2503
   162
skamonkey@3333
   163
	GameRulesNativesInit();
skamonkey@3333
   164
dvander@2503
   165
	InitSDKToolsAPI();
dvander@2503
   166
ds@783
   167
	return true;
ds@783
   168
}
ds@783
   169
dvander@950
   170
void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
dvander@950
   171
{
dvander@950
   172
	if (type == g_CallHandle)
dvander@950
   173
	{
dvander@950
   174
		ValveCall *v = (ValveCall *)object;
dvander@950
   175
		delete v;
dvander@1628
   176
	}
dvander@1628
   177
	else if (type == g_TraceHandle)
dvander@1628
   178
	{
faluco@1075
   179
		trace_t *tr = (trace_t *)object;
faluco@1075
   180
		delete tr;
faluco@1075
   181
	}
dvander@950
   182
}
dvander@950
   183
dvander@950
   184
void SDKTools::SDK_OnUnload()
dvander@950
   185
{
faluco@1560
   186
	SourceHook::List<ValveCall *>::iterator iter;
dvander@954
   187
	for (iter = g_RegCalls.begin();
dvander@954
   188
		 iter != g_RegCalls.end();
dvander@954
   189
		 iter++)
dvander@954
   190
	{
dvander@954
   191
		delete (*iter);
dvander@954
   192
	}
dvander@954
   193
	g_RegCalls.clear();
dvander@1169
   194
	ShutdownHelpers();
dvander@954
   195
faluco@1498
   196
	if (g_pAcceptInput)
faluco@1498
   197
	{
faluco@1498
   198
		g_pAcceptInput->Destroy();
faluco@1498
   199
		g_pAcceptInput = NULL;
faluco@1498
   200
	}
faluco@1498
   201
faluco@1031
   202
	g_TEManager.Shutdown();
faluco@1255
   203
	s_TempEntHooks.Shutdown();
faluco@1735
   204
	s_SoundHooks.Shutdown();
pred@2711
   205
	g_Hooks.Shutdown();
dvander@3414
   206
	g_OutputManager.Shutdown();
faluco@1031
   207
dvander@950
   208
	gameconfs->CloseGameConfigFile(g_pGameConf);
teame06@1235
   209
	playerhelpers->RemoveClientListener(&g_SdkTools);
dvander@1628
   210
	playerhelpers->UnregisterCommandTargetProcessor(this);
dvander@2060
   211
	plsys->RemovePluginsListener(&g_OutputManager);
faluco@1262
   212
kyle@3819
   213
	SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SDKTools::LevelInit), true);
faluco@1735
   214
faluco@1735
   215
	if (enginePatch)
faluco@1735
   216
	{
faluco@1735
   217
		SH_RELEASE_CALLCLASS(enginePatch);
faluco@1735
   218
		enginePatch = NULL;
faluco@1735
   219
	}
faluco@1735
   220
	if (enginesoundPatch)
faluco@1735
   221
	{
faluco@1735
   222
		SH_RELEASE_CALLCLASS(enginesoundPatch);
faluco@1735
   223
		enginesoundPatch = NULL;
faluco@1735
   224
	}
dvander@2306
   225
dvander@2306
   226
	bool err;
dvander@2306
   227
	if (g_CallHandle != 0)
dvander@2306
   228
	{
dvander@2306
   229
		if ((err = handlesys->RemoveType(g_CallHandle, myself->GetIdentity())) != true)
dvander@2306
   230
		{
dvander@2306
   231
			g_pSM->LogError(myself, "Could not remove call handle (type=%x, err=%d)", g_CallHandle, err);
dvander@2306
   232
		}
dvander@2306
   233
	}
dvander@2306
   234
dvander@2306
   235
	if (g_TraceHandle != 0)
dvander@2306
   236
	{
dvander@2306
   237
		if ((err = handlesys->RemoveType(g_TraceHandle, myself->GetIdentity())) != true)
dvander@2306
   238
		{
dvander@2306
   239
			g_pSM->LogError(myself, "Could not remove trace handle (type=%x, err=%d)", g_TraceHandle, err);
dvander@2306
   240
		}
dvander@2306
   241
	}
dvander@950
   242
}
dvander@950
   243
ds@783
   244
bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
ds@783
   245
{
faluco@1560
   246
	GET_V_IFACE_ANY(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
faluco@1560
   247
	GET_V_IFACE_ANY(GetEngineFactory, engsound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
faluco@1560
   248
	GET_V_IFACE_ANY(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER);
faluco@1560
   249
	GET_V_IFACE_ANY(GetEngineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER);
faluco@1560
   250
	GET_V_IFACE_ANY(GetEngineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
faluco@1560
   251
	GET_V_IFACE_ANY(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
faluco@1560
   252
	GET_V_IFACE_ANY(GetEngineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER);
faluco@1560
   253
	GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER);
faluco@1560
   254
	GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
ds@783
   255
skamonkey@3280
   256
#if SOURCE_ENGINE >= SE_ORANGEBOX
skamonkey@3280
   257
	GET_V_IFACE_ANY(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION);
skamonkey@3280
   258
#endif
skamonkey@3280
   259
ds@2400
   260
	gpGlobals = ismm->GetCGlobals();
faluco@1735
   261
	enginePatch = SH_GET_CALLCLASS(engine);
faluco@1735
   262
	enginesoundPatch = SH_GET_CALLCLASS(engsound);
faluco@1735
   263
ds@783
   264
	return true;
ds@783
   265
}
ds@783
   266
ds@783
   267
void SDKTools::SDK_OnAllLoaded()
ds@783
   268
{
ds@783
   269
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
ds@1065
   270
dvander@1757
   271
	if (!g_pBinTools)
dvander@1757
   272
	{
dvander@1757
   273
		return;
dvander@1757
   274
	}
dvander@1757
   275
faluco@1031
   276
	g_TEManager.Initialize();
faluco@1255
   277
	s_TempEntHooks.Initialize();
faluco@1735
   278
	s_SoundHooks.Initialize();
pred@2711
   279
	g_Hooks.Initialize();
ds@1240
   280
	InitializeValveGlobals();
ds@783
   281
}
ds@783
   282
skamonkey@3816
   283
void SDKTools::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
skamonkey@3816
   284
{
skamonkey@3816
   285
	InitTeamNatives();
skamonkey@3816
   286
	GetResourceEntity();
skamonkey@3816
   287
}
skamonkey@3816
   288
ds@783
   289
bool SDKTools::QueryRunning(char *error, size_t maxlength)
ds@783
   290
{
ds@783
   291
	SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
ds@783
   292
ds@783
   293
	return true;
ds@783
   294
}
dvander@1023
   295
dvander@1023
   296
bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface)
dvander@1023
   297
{
dvander@1023
   298
	if (pInterface == g_pBinTools)
dvander@1023
   299
	{
dvander@1023
   300
		return false;
dvander@1023
   301
	}
dvander@1023
   302
dvander@1023
   303
	return IExtensionInterface::QueryInterfaceDrop(pInterface);
dvander@1023
   304
}
dvander@1023
   305
dvander@1023
   306
void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface)
dvander@1023
   307
{
faluco@1560
   308
	SourceHook::List<ValveCall *>::iterator iter;
dvander@1023
   309
	for (iter = g_RegCalls.begin();
dvander@1023
   310
		iter != g_RegCalls.end();
dvander@1023
   311
		iter++)
dvander@1023
   312
	{
dvander@1023
   313
		delete (*iter);
dvander@1023
   314
	}
dvander@1023
   315
	g_RegCalls.clear();
dvander@1169
   316
	ShutdownHelpers();
dvander@1023
   317
faluco@1031
   318
	g_TEManager.Shutdown();
faluco@1255
   319
	s_TempEntHooks.Shutdown();
faluco@1498
   320
faluco@1498
   321
	if (g_pAcceptInput)
faluco@1498
   322
	{
faluco@1498
   323
		g_pAcceptInput->Destroy();
faluco@1498
   324
		g_pAcceptInput = NULL;
faluco@1498
   325
	}
dvander@1023
   326
}
dvander@1052
   327
dvander@1052
   328
bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar)
dvander@1052
   329
{
faluco@1560
   330
#if defined METAMOD_PLAPI_VERSION
faluco@1560
   331
	return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
faluco@1560
   332
#else
dvander@1052
   333
	return g_SMAPI->RegisterConCmdBase(g_PLAPI, pVar);
faluco@1560
   334
#endif
dvander@1052
   335
}
faluco@1262
   336
faluco@1262
   337
bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
faluco@1262
   338
{
faluco@1262
   339
	const char *name;
faluco@1262
   340
	char key[32];
faluco@1262
   341
	int count, n = 1;
faluco@1262
   342
faluco@1262
   343
	if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount")))
faluco@1262
   344
	{
faluco@1262
   345
		RETURN_META_VALUE(MRES_IGNORED, true);
faluco@1262
   346
	}
faluco@1262
   347
faluco@1262
   348
	count = atoi(name);
faluco@1262
   349
faluco@1262
   350
	while (n <= count)
faluco@1262
   351
	{
faluco@1262
   352
		snprintf(key, sizeof(key), "SlapSound%d", n);
faluco@1262
   353
		if ((name=g_pGameConf->GetKeyValue(key)))
faluco@1262
   354
		{
faluco@1262
   355
			engsound->PrecacheSound(name, true);
faluco@1262
   356
		}
faluco@1262
   357
		n++;
faluco@1262
   358
	}
faluco@1262
   359
faluco@1262
   360
	RETURN_META_VALUE(MRES_IGNORED, true);
faluco@1262
   361
}
dvander@1628
   362
dvander@1628
   363
bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
dvander@1628
   364
{
dvander@1628
   365
	IGamePlayer *pAdmin = info->admin ? playerhelpers->GetGamePlayer(info->admin) : NULL;
dvander@1628
   366
dvander@2838
   367
	if (strcmp(info->pattern, "@aim") == 0)
dvander@1628
   368
	{
dvander@2838
   369
		/* The server can't aim, of course. */
dvander@2838
   370
		if (pAdmin == NULL)
dvander@2838
   371
		{
dvander@2838
   372
			return false;
dvander@2838
   373
		}
dvander@2838
   374
dvander@2838
   375
		int player_index;
dvander@2838
   376
		if ((player_index = GetClientAimTarget(pAdmin->GetEdict(), true)) < 1)
dvander@2838
   377
		{
dvander@2838
   378
			info->reason = COMMAND_TARGET_NONE;
dvander@2838
   379
			info->num_targets = 0;
dvander@2838
   380
			return true;
dvander@2838
   381
		}
dvander@2838
   382
dvander@2838
   383
		IGamePlayer *pTarget = playerhelpers->GetGamePlayer(player_index);
dvander@2838
   384
dvander@2838
   385
		if (pTarget == NULL)
dvander@2838
   386
		{
dvander@2838
   387
			info->reason = COMMAND_TARGET_NONE;
dvander@2838
   388
			info->num_targets = 0;
dvander@2838
   389
			return true;
dvander@2838
   390
		}
dvander@2838
   391
dvander@2838
   392
		info->reason = playerhelpers->FilterCommandTarget(pAdmin, pTarget, info->flags);
dvander@2838
   393
		if (info->reason != COMMAND_TARGET_VALID)
dvander@2838
   394
		{
dvander@2838
   395
			info->num_targets = 0;
dvander@2838
   396
			return true;
dvander@2838
   397
		}
dvander@1628
   398
dvander@2838
   399
		info->targets[0] = player_index;
dvander@2838
   400
		info->num_targets = 1;
dvander@2838
   401
		info->reason = COMMAND_TARGET_VALID;
dvander@2838
   402
		info->target_name_style = COMMAND_TARGETNAME_RAW;
dvander@2838
   403
		snprintf(info->target_name, info->target_name_maxlength, "%s", pTarget->GetName());
dvander@2838
   404
		return true;
dvander@2838
   405
	}
dvander@2838
   406
	else if (strcmp(info->pattern, "@spec") == 0)
dvander@1628
   407
	{
dvander@2838
   408
		const char *teamname = tools_GetTeamName(1);
dvander@2838
   409
		if (strcasecmp(teamname, "spectator") != 0)
dvander@2838
   410
			return false;
dvander@1757
   411
		info->num_targets = 0;
dvander@2838
   412
		for (int i = 1; i <= playerhelpers->GetMaxClients(); i++)
dvander@2838
   413
		{
dvander@2838
   414
			IGamePlayer *player = playerhelpers->GetGamePlayer(i);
dvander@2838
   415
			if (player == NULL || !player->IsInGame())
dvander@2838
   416
				continue;
dvander@2838
   417
			IPlayerInfo *plinfo = player->GetPlayerInfo();
dvander@2838
   418
			if (plinfo == NULL)
dvander@2838
   419
				continue;
dvander@2838
   420
			if (plinfo->GetTeamIndex() == 1 &&
dvander@2838
   421
			    playerhelpers->FilterCommandTarget(pAdmin, player, info->flags) ==
dvander@2838
   422
				COMMAND_TARGET_VALID)
dvander@2838
   423
			{
dvander@2838
   424
				info->targets[info->num_targets++] = i;
dvander@2838
   425
			}
dvander@2838
   426
		}
dvander@2838
   427
		info->reason = info->num_targets > 0 ? COMMAND_TARGET_VALID : COMMAND_TARGET_EMPTY_FILTER;
dvander@2838
   428
		info->target_name_style = COMMAND_TARGETNAME_ML;
dvander@2838
   429
		snprintf(info->target_name, info->target_name_maxlength, "all spectators");
dvander@1757
   430
		return true;
dvander@1628
   431
	}
dvander@1628
   432
dvander@2838
   433
	return false;
dvander@1628
   434
}
dvander@2503
   435
dvander@2790
   436
const char *SDKTools::GetExtensionVerString()
pred@2711
   437
{
asherkin@3630
   438
	return SM_VERSION_STRING;
dvander@2783
   439
}
dvander@2783
   440
dvander@2790
   441
const char *SDKTools::GetExtensionDateString()
dvander@2783
   442
{
dvander@2783
   443
	return SM_BUILD_TIMESTAMP;
pred@2711
   444
}
pred@2711
   445
dvander@2786
   446
void SDKTools::OnClientPutInServer(int client)
dvander@2786
   447
{
dvander@2786
   448
	g_Hooks.OnClientPutInServer(client);
dvander@2786
   449
}
dvander@2786
   450
dvander@2503
   451
class SDKTools_API : public ISDKTools
dvander@2503
   452
{
dvander@2503
   453
public:
dvander@2503
   454
	virtual const char *GetInterfaceName()
dvander@2503
   455
	{
dvander@2503
   456
		return SMINTERFACE_SDKTOOLS_NAME;
dvander@2503
   457
	}
dvander@2503
   458
dvander@2503
   459
	virtual unsigned int GetInterfaceVersion()
dvander@2503
   460
	{
dvander@2503
   461
		return SMINTERFACE_SDKTOOLS_VERSION;
dvander@2503
   462
	}
dvander@2503
   463
dvander@2503
   464
	virtual IServer *GetIServer()
dvander@2503
   465
	{
dvander@2503
   466
		return iserver;
dvander@2503
   467
	}
skamonkey@3157
   468
	
skamonkey@3157
   469
	virtual void *GetGameRules()
skamonkey@3157
   470
	{
skamonkey@3157
   471
		if (!g_pGameRules)
skamonkey@3157
   472
			return NULL;
skamonkey@3157
   473
		
skamonkey@3157
   474
		return *g_pGameRules;
skamonkey@3157
   475
	}
dvander@2503
   476
} g_SDKTools_API;
dvander@2503
   477
dvander@2503
   478
static void InitSDKToolsAPI()
dvander@2503
   479
{
dvander@2503
   480
	g_pSDKTools = &g_SDKTools_API;
dvander@2503
   481
	sharesys->AddInterface(myself, g_pSDKTools);
dvander@2503
   482
}