extensions/sdktools/extension.cpp
author Scott Ehlert <ds@alliedmods.net>
Sat May 29 18:11:47 2010 -0400 (2010-05-29)
changeset 3027 0f90dd9754ca
parent 2838 d0b440ee7a64
child 3089 5e3628933a4a
permissions -rw-r--r--
Fixed various areas where code was being compiled for Linux only, but should actually be used on OS X too (bug 4392, r=dvander).
ds@783
     1
/**
ds@783
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1233
     4
 * SourceMod SDKTools Extension
ds@1947
     5
 * Copyright (C) 2004-2008 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"
dvander@2503
    43
#include <ISDKTools.h>
ds@783
    44
ds@783
    45
/**
ds@783
    46
 * @file extension.cpp
ds@995
    47
 * @brief Implements SDK Tools extension code.
ds@783
    48
 */
ds@783
    49
faluco@1262
    50
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
faluco@1262
    51
ds@783
    52
SDKTools g_SdkTools;		/**< Global singleton for extension's main interface */
ds@783
    53
IServerGameEnts *gameents = NULL;
faluco@1075
    54
IEngineTrace *enginetrace = NULL;
ds@1114
    55
IEngineSound *engsound = NULL;
ds@1114
    56
INetworkStringTableContainer *netstringtables = NULL;
dvander@1169
    57
IServerPluginHelpers *pluginhelpers = NULL;
ds@783
    58
IBinTools *g_pBinTools = NULL;
dvander@950
    59
IGameConfig *g_pGameConf = NULL;
faluco@1031
    60
IGameHelpers *g_pGameHelpers = NULL;
faluco@1219
    61
IServerGameClients *serverClients = NULL;
ds@1240
    62
IVoiceServer *voiceserver = NULL;
teame06@1239
    63
IPlayerInfoManager *playerinfomngr = NULL;
faluco@1560
    64
ICvar *icvar = NULL;
faluco@1769
    65
IServer *iserver = NULL;
ds@2400
    66
CGlobalVars *gpGlobals;
faluco@1735
    67
SourceHook::CallClass<IVEngineServer> *enginePatch = NULL;
faluco@1735
    68
SourceHook::CallClass<IEngineSound> *enginesoundPatch = NULL;
dvander@950
    69
HandleType_t g_CallHandle = 0;
faluco@1075
    70
HandleType_t g_TraceHandle = 0;
dvander@2503
    71
ISDKTools *g_pSDKTools;
ds@783
    72
ds@783
    73
SMEXT_LINK(&g_SdkTools);
ds@783
    74
dvander@950
    75
extern sp_nativeinfo_t g_CallNatives[];
faluco@1031
    76
extern sp_nativeinfo_t g_TENatives[];
faluco@1075
    77
extern sp_nativeinfo_t g_TRNatives[];
ds@1114
    78
extern sp_nativeinfo_t g_StringTableNatives[];
teame06@1235
    79
extern sp_nativeinfo_t g_VoiceNatives[];
faluco@1498
    80
extern sp_nativeinfo_t g_EntInputNatives[];
faluco@1613
    81
extern sp_nativeinfo_t g_TeamNatives[];
dvander@950
    82
dvander@2503
    83
static void InitSDKToolsAPI();
dvander@2503
    84
ds@783
    85
bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
ds@783
    86
{
dvander@2306
    87
	HandleError err;
dvander@2306
    88
dvander@2529
    89
	if (!gameconfs->LoadGameConfigFile("sdktools.games", &g_pGameConf, error, maxlength))
pred@2124
    90
	{
pred@2124
    91
		return false;
pred@2124
    92
	}
pred@2124
    93
dvander@950
    94
	sharesys->AddDependency(myself, "bintools.ext", true, true);
dvander@950
    95
	sharesys->AddNatives(myself, g_CallNatives);
dvander@954
    96
	sharesys->AddNatives(myself, g_Natives);
faluco@1031
    97
	sharesys->AddNatives(myself, g_TENatives);
dvander@1047
    98
	sharesys->AddNatives(myself, g_SoundNatives);
faluco@1075
    99
	sharesys->AddNatives(myself, g_TRNatives);
ds@1114
   100
	sharesys->AddNatives(myself, g_StringTableNatives);
teame06@1235
   101
	sharesys->AddNatives(myself, g_VoiceNatives);
faluco@1498
   102
	sharesys->AddNatives(myself, g_EntInputNatives);
faluco@1613
   103
	sharesys->AddNatives(myself, g_TeamNatives);
pred@1958
   104
	sharesys->AddNatives(myself, g_EntOutputNatives);
faluco@1031
   105
faluco@1031
   106
	SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
ds@783
   107
teame06@1235
   108
	playerhelpers->AddClientListener(&g_SdkTools);
dvander@2306
   109
	g_CallHandle = handlesys->CreateType("ValveCall", this, 0, NULL, NULL, myself->GetIdentity(), &err);
dvander@2306
   110
	if (g_CallHandle == 0)
dvander@2306
   111
	{
dvander@2306
   112
		snprintf(error, maxlength, "Could not create call handle type (err: %d)", err);	
dvander@2306
   113
		return false;
dvander@2306
   114
	}
pred@2108
   115
pred@2108
   116
	TypeAccess TraceAccess;
pred@2108
   117
	handlesys->InitAccessDefaults(&TraceAccess, NULL);
pred@2116
   118
	TraceAccess.ident = myself->GetIdentity();
pred@2108
   119
	TraceAccess.access[HTypeAccess_Create] = true;
pred@2116
   120
	TraceAccess.access[HTypeAccess_Inherit] = true;
dvander@2306
   121
	g_TraceHandle = handlesys->CreateType("TraceRay", this, 0, &TraceAccess, NULL, myself->GetIdentity(), &err);
dvander@2306
   122
	if (g_TraceHandle == 0)
dvander@2306
   123
	{
dvander@2306
   124
		handlesys->RemoveType(g_CallHandle, myself->GetIdentity());
dvander@2306
   125
		g_CallHandle = 0;
dvander@2306
   126
		snprintf(error, maxlength, "Could not create traceray handle type (err: %d)", err);
dvander@2306
   127
		return false;
dvander@2306
   128
	}
ds@783
   129
ds@2400
   130
#if SOURCE_ENGINE >= SE_ORANGEBOX
faluco@1560
   131
	g_pCVar = icvar;
faluco@1560
   132
#endif
faluco@1560
   133
	CONVAR_REGISTER(this);
dvander@1052
   134
faluco@1262
   135
	SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
faluco@1262
   136
dvander@1628
   137
	playerhelpers->RegisterCommandTargetProcessor(this);
dvander@1628
   138
dvander@1611
   139
	MathLib_Init(2.2f, 2.2f, 0.0f, 2);
dvander@1611
   140
pred@1958
   141
	spengine = g_pSM->GetScriptingEngine();
pred@1958
   142
pred@1958
   143
	plsys->AddPluginsListener(&g_OutputManager);
pred@1958
   144
pred@1958
   145
	g_OutputManager.Init();
pred@1958
   146
dvander@2044
   147
	VoiceInit();
dvander@2044
   148
dvander@2503
   149
	GetIServer();
dvander@2503
   150
dvander@2503
   151
	InitSDKToolsAPI();
dvander@2503
   152
ds@783
   153
	return true;
ds@783
   154
}
ds@783
   155
dvander@950
   156
void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
dvander@950
   157
{
dvander@950
   158
	if (type == g_CallHandle)
dvander@950
   159
	{
dvander@950
   160
		ValveCall *v = (ValveCall *)object;
dvander@950
   161
		delete v;
dvander@1628
   162
	}
dvander@1628
   163
	else if (type == g_TraceHandle)
dvander@1628
   164
	{
faluco@1075
   165
		trace_t *tr = (trace_t *)object;
faluco@1075
   166
		delete tr;
faluco@1075
   167
	}
dvander@950
   168
}
dvander@950
   169
dvander@950
   170
void SDKTools::SDK_OnUnload()
dvander@950
   171
{
faluco@1560
   172
	SourceHook::List<ValveCall *>::iterator iter;
dvander@954
   173
	for (iter = g_RegCalls.begin();
dvander@954
   174
		 iter != g_RegCalls.end();
dvander@954
   175
		 iter++)
dvander@954
   176
	{
dvander@954
   177
		delete (*iter);
dvander@954
   178
	}
dvander@954
   179
	g_RegCalls.clear();
dvander@1169
   180
	ShutdownHelpers();
dvander@954
   181
faluco@1498
   182
	if (g_pAcceptInput)
faluco@1498
   183
	{
faluco@1498
   184
		g_pAcceptInput->Destroy();
faluco@1498
   185
		g_pAcceptInput = NULL;
faluco@1498
   186
	}
faluco@1498
   187
faluco@1031
   188
	g_TEManager.Shutdown();
faluco@1255
   189
	s_TempEntHooks.Shutdown();
faluco@1735
   190
	s_SoundHooks.Shutdown();
pred@2711
   191
	g_Hooks.Shutdown();
faluco@1031
   192
dvander@950
   193
	gameconfs->CloseGameConfigFile(g_pGameConf);
teame06@1235
   194
	playerhelpers->RemoveClientListener(&g_SdkTools);
dvander@1628
   195
	playerhelpers->UnregisterCommandTargetProcessor(this);
dvander@2060
   196
	plsys->RemovePluginsListener(&g_OutputManager);
faluco@1262
   197
faluco@1262
   198
	SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
faluco@1735
   199
faluco@1735
   200
	if (enginePatch)
faluco@1735
   201
	{
faluco@1735
   202
		SH_RELEASE_CALLCLASS(enginePatch);
faluco@1735
   203
		enginePatch = NULL;
faluco@1735
   204
	}
faluco@1735
   205
	if (enginesoundPatch)
faluco@1735
   206
	{
faluco@1735
   207
		SH_RELEASE_CALLCLASS(enginesoundPatch);
faluco@1735
   208
		enginesoundPatch = NULL;
faluco@1735
   209
	}
dvander@2306
   210
dvander@2306
   211
	bool err;
dvander@2306
   212
	if (g_CallHandle != 0)
dvander@2306
   213
	{
dvander@2306
   214
		if ((err = handlesys->RemoveType(g_CallHandle, myself->GetIdentity())) != true)
dvander@2306
   215
		{
dvander@2306
   216
			g_pSM->LogError(myself, "Could not remove call handle (type=%x, err=%d)", g_CallHandle, err);
dvander@2306
   217
		}
dvander@2306
   218
	}
dvander@2306
   219
dvander@2306
   220
	if (g_TraceHandle != 0)
dvander@2306
   221
	{
dvander@2306
   222
		if ((err = handlesys->RemoveType(g_TraceHandle, myself->GetIdentity())) != true)
dvander@2306
   223
		{
dvander@2306
   224
			g_pSM->LogError(myself, "Could not remove trace handle (type=%x, err=%d)", g_TraceHandle, err);
dvander@2306
   225
		}
dvander@2306
   226
	}
dvander@950
   227
}
dvander@950
   228
ds@783
   229
bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
ds@783
   230
{
faluco@1560
   231
	GET_V_IFACE_ANY(GetServerFactory, gameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS);
faluco@1560
   232
	GET_V_IFACE_ANY(GetEngineFactory, engsound, IEngineSound, IENGINESOUND_SERVER_INTERFACE_VERSION);
faluco@1560
   233
	GET_V_IFACE_ANY(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER);
faluco@1560
   234
	GET_V_IFACE_ANY(GetEngineFactory, netstringtables, INetworkStringTableContainer, INTERFACENAME_NETWORKSTRINGTABLESERVER);
faluco@1560
   235
	GET_V_IFACE_ANY(GetEngineFactory, pluginhelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS);
faluco@1560
   236
	GET_V_IFACE_ANY(GetServerFactory, serverClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
faluco@1560
   237
	GET_V_IFACE_ANY(GetEngineFactory, voiceserver, IVoiceServer, INTERFACEVERSION_VOICESERVER);
faluco@1560
   238
	GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER);
faluco@1560
   239
	GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
ds@783
   240
ds@2400
   241
	gpGlobals = ismm->GetCGlobals();
faluco@1735
   242
	enginePatch = SH_GET_CALLCLASS(engine);
faluco@1735
   243
	enginesoundPatch = SH_GET_CALLCLASS(engsound);
faluco@1735
   244
ds@783
   245
	return true;
ds@783
   246
}
ds@783
   247
ds@783
   248
void SDKTools::SDK_OnAllLoaded()
ds@783
   249
{
ds@783
   250
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
ds@1065
   251
dvander@1757
   252
	if (!g_pBinTools)
dvander@1757
   253
	{
dvander@1757
   254
		return;
dvander@1757
   255
	}
dvander@1757
   256
faluco@1031
   257
	g_TEManager.Initialize();
faluco@1255
   258
	s_TempEntHooks.Initialize();
faluco@1735
   259
	s_SoundHooks.Initialize();
pred@2711
   260
	g_Hooks.Initialize();
ds@1240
   261
	InitializeValveGlobals();
ds@783
   262
}
ds@783
   263
ds@783
   264
bool SDKTools::QueryRunning(char *error, size_t maxlength)
ds@783
   265
{
ds@783
   266
	SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
ds@783
   267
ds@783
   268
	return true;
ds@783
   269
}
dvander@1023
   270
dvander@1023
   271
bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface)
dvander@1023
   272
{
dvander@1023
   273
	if (pInterface == g_pBinTools)
dvander@1023
   274
	{
dvander@1023
   275
		return false;
dvander@1023
   276
	}
dvander@1023
   277
dvander@1023
   278
	return IExtensionInterface::QueryInterfaceDrop(pInterface);
dvander@1023
   279
}
dvander@1023
   280
dvander@1023
   281
void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface)
dvander@1023
   282
{
faluco@1560
   283
	SourceHook::List<ValveCall *>::iterator iter;
dvander@1023
   284
	for (iter = g_RegCalls.begin();
dvander@1023
   285
		iter != g_RegCalls.end();
dvander@1023
   286
		iter++)
dvander@1023
   287
	{
dvander@1023
   288
		delete (*iter);
dvander@1023
   289
	}
dvander@1023
   290
	g_RegCalls.clear();
dvander@1169
   291
	ShutdownHelpers();
dvander@1023
   292
faluco@1031
   293
	g_TEManager.Shutdown();
faluco@1255
   294
	s_TempEntHooks.Shutdown();
faluco@1498
   295
faluco@1498
   296
	if (g_pAcceptInput)
faluco@1498
   297
	{
faluco@1498
   298
		g_pAcceptInput->Destroy();
faluco@1498
   299
		g_pAcceptInput = NULL;
faluco@1498
   300
	}
dvander@1023
   301
}
dvander@1052
   302
dvander@1052
   303
bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar)
dvander@1052
   304
{
faluco@1560
   305
#if defined METAMOD_PLAPI_VERSION
faluco@1560
   306
	return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar);
faluco@1560
   307
#else
dvander@1052
   308
	return g_SMAPI->RegisterConCmdBase(g_PLAPI, pVar);
faluco@1560
   309
#endif
dvander@1052
   310
}
faluco@1262
   311
faluco@1262
   312
bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
faluco@1262
   313
{
faluco@1262
   314
	const char *name;
faluco@1262
   315
	char key[32];
faluco@1262
   316
	int count, n = 1;
faluco@1262
   317
faluco@1262
   318
	if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount")))
faluco@1262
   319
	{
faluco@1262
   320
		RETURN_META_VALUE(MRES_IGNORED, true);
faluco@1262
   321
	}
faluco@1262
   322
faluco@1262
   323
	count = atoi(name);
faluco@1262
   324
faluco@1262
   325
	while (n <= count)
faluco@1262
   326
	{
faluco@1262
   327
		snprintf(key, sizeof(key), "SlapSound%d", n);
faluco@1262
   328
		if ((name=g_pGameConf->GetKeyValue(key)))
faluco@1262
   329
		{
faluco@1262
   330
			engsound->PrecacheSound(name, true);
faluco@1262
   331
		}
faluco@1262
   332
		n++;
faluco@1262
   333
	}
faluco@1262
   334
faluco@1262
   335
	RETURN_META_VALUE(MRES_IGNORED, true);
faluco@1262
   336
}
dvander@1628
   337
dvander@1628
   338
bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info)
dvander@1628
   339
{
dvander@1628
   340
	IGamePlayer *pAdmin = info->admin ? playerhelpers->GetGamePlayer(info->admin) : NULL;
dvander@1628
   341
dvander@2838
   342
	if (strcmp(info->pattern, "@aim") == 0)
dvander@1628
   343
	{
dvander@2838
   344
		/* The server can't aim, of course. */
dvander@2838
   345
		if (pAdmin == NULL)
dvander@2838
   346
		{
dvander@2838
   347
			return false;
dvander@2838
   348
		}
dvander@2838
   349
dvander@2838
   350
		int player_index;
dvander@2838
   351
		if ((player_index = GetClientAimTarget(pAdmin->GetEdict(), true)) < 1)
dvander@2838
   352
		{
dvander@2838
   353
			info->reason = COMMAND_TARGET_NONE;
dvander@2838
   354
			info->num_targets = 0;
dvander@2838
   355
			return true;
dvander@2838
   356
		}
dvander@2838
   357
dvander@2838
   358
		IGamePlayer *pTarget = playerhelpers->GetGamePlayer(player_index);
dvander@2838
   359
dvander@2838
   360
		if (pTarget == NULL)
dvander@2838
   361
		{
dvander@2838
   362
			info->reason = COMMAND_TARGET_NONE;
dvander@2838
   363
			info->num_targets = 0;
dvander@2838
   364
			return true;
dvander@2838
   365
		}
dvander@2838
   366
dvander@2838
   367
		info->reason = playerhelpers->FilterCommandTarget(pAdmin, pTarget, info->flags);
dvander@2838
   368
		if (info->reason != COMMAND_TARGET_VALID)
dvander@2838
   369
		{
dvander@2838
   370
			info->num_targets = 0;
dvander@2838
   371
			return true;
dvander@2838
   372
		}
dvander@1628
   373
dvander@2838
   374
		info->targets[0] = player_index;
dvander@2838
   375
		info->num_targets = 1;
dvander@2838
   376
		info->reason = COMMAND_TARGET_VALID;
dvander@2838
   377
		info->target_name_style = COMMAND_TARGETNAME_RAW;
dvander@2838
   378
		snprintf(info->target_name, info->target_name_maxlength, "%s", pTarget->GetName());
dvander@2838
   379
		return true;
dvander@2838
   380
	}
dvander@2838
   381
	else if (strcmp(info->pattern, "@spec") == 0)
dvander@1628
   382
	{
dvander@2838
   383
		const char *teamname = tools_GetTeamName(1);
dvander@2838
   384
		if (strcasecmp(teamname, "spectator") != 0)
dvander@2838
   385
			return false;
dvander@1757
   386
		info->num_targets = 0;
dvander@2838
   387
		for (int i = 1; i <= playerhelpers->GetMaxClients(); i++)
dvander@2838
   388
		{
dvander@2838
   389
			IGamePlayer *player = playerhelpers->GetGamePlayer(i);
dvander@2838
   390
			if (player == NULL || !player->IsInGame())
dvander@2838
   391
				continue;
dvander@2838
   392
			IPlayerInfo *plinfo = player->GetPlayerInfo();
dvander@2838
   393
			if (plinfo == NULL)
dvander@2838
   394
				continue;
dvander@2838
   395
			if (plinfo->GetTeamIndex() == 1 &&
dvander@2838
   396
			    playerhelpers->FilterCommandTarget(pAdmin, player, info->flags) ==
dvander@2838
   397
				COMMAND_TARGET_VALID)
dvander@2838
   398
			{
dvander@2838
   399
				info->targets[info->num_targets++] = i;
dvander@2838
   400
			}
dvander@2838
   401
		}
dvander@2838
   402
		info->reason = info->num_targets > 0 ? COMMAND_TARGET_VALID : COMMAND_TARGET_EMPTY_FILTER;
dvander@2838
   403
		info->target_name_style = COMMAND_TARGETNAME_ML;
dvander@2838
   404
		snprintf(info->target_name, info->target_name_maxlength, "all spectators");
dvander@1757
   405
		return true;
dvander@1628
   406
	}
dvander@1628
   407
dvander@2838
   408
	return false;
dvander@1628
   409
}
dvander@2503
   410
dvander@2790
   411
const char *SDKTools::GetExtensionVerString()
pred@2711
   412
{
dvander@2783
   413
	return SM_FULL_VERSION;
dvander@2783
   414
}
dvander@2783
   415
dvander@2790
   416
const char *SDKTools::GetExtensionDateString()
dvander@2783
   417
{
dvander@2783
   418
	return SM_BUILD_TIMESTAMP;
pred@2711
   419
}
pred@2711
   420
dvander@2786
   421
void SDKTools::OnClientPutInServer(int client)
dvander@2786
   422
{
dvander@2786
   423
	g_Hooks.OnClientPutInServer(client);
dvander@2786
   424
}
dvander@2786
   425
dvander@2503
   426
class SDKTools_API : public ISDKTools
dvander@2503
   427
{
dvander@2503
   428
public:
dvander@2503
   429
	virtual const char *GetInterfaceName()
dvander@2503
   430
	{
dvander@2503
   431
		return SMINTERFACE_SDKTOOLS_NAME;
dvander@2503
   432
	}
dvander@2503
   433
dvander@2503
   434
	virtual unsigned int GetInterfaceVersion()
dvander@2503
   435
	{
dvander@2503
   436
		return SMINTERFACE_SDKTOOLS_VERSION;
dvander@2503
   437
	}
dvander@2503
   438
dvander@2503
   439
	virtual IServer *GetIServer()
dvander@2503
   440
	{
dvander@2503
   441
		return iserver;
dvander@2503
   442
	}
dvander@2503
   443
} g_SDKTools_API;
dvander@2503
   444
dvander@2503
   445
static void InitSDKToolsAPI()
dvander@2503
   446
{
dvander@2503
   447
	g_pSDKTools = &g_SDKTools_API;
dvander@2503
   448
	sharesys->AddInterface(myself, g_pSDKTools);
dvander@2503
   449
}