public/IExtensionSys.h
author Nicholas Hastings <skamonkey@gmail.com>
Thu Nov 08 12:56:19 2012 -0500 (2012-11-08)
changeset 3684 331fde6fdb17
parent 2841 dde3dd0b4b8b
child 3872 4c93f74cae51
permissions -rw-r--r--
Fixed typo in game.nucleardawn.txt.
dvander@372
     1
/**
dvander@375
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1226
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@372
     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@379
    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@1226
    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@1226
    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>.
dvander@372
    28
 *
dvander@372
    29
 * Version: $Id$
dvander@372
    30
 */
dvander@372
    31
dvander@324
    32
#ifndef _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
dvander@324
    33
#define _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
dvander@324
    34
dvander@324
    35
#include <IShareSys.h>
dvander@324
    36
#include <ILibrarySys.h>
dvander@324
    37
dvander@372
    38
/**
dvander@372
    39
 * @file IExtensionSys.h
dvander@372
    40
 * @brief Defines the interface for loading/unloading/managing extensions.
dvander@372
    41
 */
dvander@372
    42
faluco@1993
    43
struct edict_t;
faluco@1993
    44
dvander@324
    45
namespace SourceMod
dvander@324
    46
{
dvander@324
    47
	class IExtensionInterface;
dvander@372
    48
	typedef void *		ITERATOR;		/**< Generic pointer for dependency iterators */
dvander@324
    49
dvander@324
    50
	/** 
dvander@372
    51
	 * @brief Encapsulates an IExtensionInterface and its dependencies.
dvander@324
    52
	 */
dvander@324
    53
	class IExtension
dvander@324
    54
	{
dvander@324
    55
	public:
dvander@324
    56
		/**
dvander@324
    57
		 * @brief Returns whether or not the extension is properly loaded.
dvander@324
    58
		 */
dvander@324
    59
		virtual bool IsLoaded() =0;
dvander@324
    60
dvander@324
    61
		/**
dvander@324
    62
		 * @brief Returns the extension's API interface
dvander@324
    63
		 *
dvander@324
    64
		 * @return			An IExtensionInterface pointer.
dvander@324
    65
		 */
dvander@324
    66
		virtual IExtensionInterface *GetAPI() =0;
dvander@324
    67
dvander@324
    68
		/**
dvander@324
    69
		 * @brief Returns the filename of the extension, relative to the
dvander@1648
    70
		 * extension folder.   If the extension is an "external" extension, 
dvander@1648
    71
		 * the file path is specified by the extension itself, and may be 
dvander@1648
    72
		 * arbitrary (not real).
dvander@324
    73
		 *
dvander@324
    74
		 * @return			A string containing the extension file name.
dvander@324
    75
		 */
dvander@324
    76
		virtual const char *GetFilename() =0;
dvander@324
    77
dvander@324
    78
		/**
dvander@324
    79
		 * @brief Returns the extension's identity token.
dvander@324
    80
		 *
dvander@324
    81
		 * @return			An IdentityToken_t pointer.
dvander@324
    82
		 */
dvander@324
    83
		virtual IdentityToken_t *GetIdentity() =0;
dvander@324
    84
dvander@324
    85
		/**
dvander@324
    86
		 * @brief Retrieves the extension dependency list for this extension.
dvander@324
    87
		 *
dvander@324
    88
		 * @param pOwner		Optional pointer to store the first interface's owner.
dvander@324
    89
		 * @param pInterface	Optional pointer to store the first interface.
dvander@324
    90
		 * @return				An ITERATOR pointer for the results, or NULL if no results at all.
dvander@324
    91
		 */
dvander@324
    92
		virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
dvander@324
    93
dvander@324
    94
		/**
dvander@324
    95
		 * @brief Finds the next dependency in the dependency list.
dvander@324
    96
		 *
dvander@324
    97
		 * @param iter			Pointer to iterator from FindFirstDependency.
dvander@324
    98
		 * @param pOwner		Optional pointer to store the interface's owner.
dvander@324
    99
		 * @param pInterface	Optional pointer to store the interface.
dvander@324
   100
		 * @return				True if there are more results after this, false otherwise.
dvander@324
   101
		 */
dvander@324
   102
		virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
dvander@324
   103
dvander@324
   104
		/**
dvander@324
   105
		 * @brief Frees an ITERATOR handle from FindFirstDependency.
dvander@324
   106
		 *
dvander@324
   107
		 * @param iter			Pointer to iterator to free.
dvander@324
   108
		 */
dvander@324
   109
		virtual void FreeDependencyIterator(ITERATOR *iter) =0;
dvander@324
   110
dvander@324
   111
		/**
dvander@324
   112
		 * @brief Queries the extension to see its run state.
dvander@324
   113
		 *
dvander@324
   114
		 * @param error			Error buffer (may be NULL).
dvander@324
   115
		 * @param maxlength		Maximum length of buffer.
dvander@324
   116
		 * @return				True if extension is okay, false if not okay.
dvander@324
   117
		 */
dvander@324
   118
		virtual bool IsRunning(char *error, size_t maxlength) =0;
dvander@1648
   119
dvander@1648
   120
		/**
dvander@1648
   121
		 * @brief Returns whether the extension is local (from the extensions 
dvander@1648
   122
		 * folder), or is from an external source (such as Metamod:Source).
dvander@1648
   123
		 *
dvander@1648
   124
		 * @return				True if from an external source, 
dvander@1648
   125
		 *						false if local to SourceMod.
dvander@1648
   126
		 */
dvander@1648
   127
		virtual bool IsExternal() =0;
dvander@324
   128
	};
dvander@324
   129
dvander@372
   130
	/**
dvander@372
   131
	 * @brief Version code of the IExtensionInterface API itself.
dvander@1689
   132
	 *
dvander@1689
   133
	 * Note: This is bumped when IShareSys is changed, because IShareSys 
dvander@1689
   134
	 * itself is not versioned.
dvander@372
   135
	 */
dvander@2841
   136
	#define SMINTERFACE_EXTENSIONAPI_VERSION	5
dvander@324
   137
dvander@324
   138
	/**
dvander@324
   139
	 * @brief The interface an extension must expose.
dvander@324
   140
	 */
dvander@324
   141
	class IExtensionInterface
dvander@324
   142
	{
dvander@324
   143
	public:
dvander@372
   144
		/** Returns the interface API version */
dvander@324
   145
		virtual unsigned int GetExtensionVersion()
dvander@324
   146
		{
dvander@324
   147
			return SMINTERFACE_EXTENSIONAPI_VERSION;
dvander@324
   148
		}
dvander@324
   149
	public:
dvander@324
   150
		/**
dvander@324
   151
		 * @brief Called when the extension is loaded.
dvander@324
   152
		 * 
dvander@324
   153
		 * @param me		Pointer back to extension.
dvander@324
   154
		 * @param sys		Pointer to interface sharing system of SourceMod.
dvander@324
   155
		 * @param error		Error buffer to print back to, if any.
ds@755
   156
		 * @param maxlength	Maximum size of error buffer.
dvander@324
   157
		 * @param late		If this extension was loaded "late" (i.e. manually).
dvander@324
   158
		 * @return			True if load should continue, false otherwise.
dvander@324
   159
		 */
dvander@324
   160
		virtual bool OnExtensionLoad(IExtension *me,
dvander@1648
   161
			IShareSys *sys, 
dvander@1648
   162
			char *error, 
dvander@1648
   163
			size_t maxlength, 
dvander@1648
   164
			bool late) =0;
dvander@324
   165
dvander@324
   166
		/**
dvander@324
   167
		 * @brief Called when the extension is about to be unloaded.
dvander@324
   168
		 */
dvander@324
   169
		virtual void OnExtensionUnload() =0;
dvander@324
   170
dvander@324
   171
		/**
dvander@324
   172
		 * @brief Called when all extensions are loaded (loading cycle is done).
dvander@324
   173
		 * If loaded late, this will be called right after OnExtensionLoad().
dvander@324
   174
		 */
dvander@324
   175
		virtual void OnExtensionsAllLoaded() =0;
dvander@324
   176
dvander@324
   177
		/**
dvander@324
   178
		 * @brief Called when your pause state is about to change.
dvander@324
   179
		 * 
dvander@324
   180
		 * @param pause		True if pausing, false if unpausing.
dvander@324
   181
		 */
dvander@324
   182
		virtual void OnExtensionPauseChange(bool pause) =0;
dvander@324
   183
dvander@324
   184
		/**
dvander@1648
   185
		 * @brief Asks the extension whether it's safe to remove an external 
dvander@1648
   186
		 * interface it's using.  If it's not safe, return false, and the 
dvander@1648
   187
		 * extension will be unloaded afterwards.
dvander@1648
   188
		 *
dvander@2134
   189
		 * NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean 
dvander@2134
   190
		 * up resources.
dvander@324
   191
		 *
dvander@2134
   192
		 * @param pInterface		Pointer to interface being dropped.  This 
dvander@2134
   193
		 * 							pointer may be opaque, and it should not 
dvander@2134
   194
		 *							be queried using SMInterface functions unless 
dvander@2134
   195
		 *							it can be verified to match an existing 
dvander@2134
   196
		 *							pointer of known type.
dvander@2134
   197
		 * @return					True to continue, false to unload this 
dvander@2134
   198
		 * 							extension afterwards.
dvander@324
   199
		 */
dvander@324
   200
		virtual bool QueryInterfaceDrop(SMInterface *pInterface)
dvander@324
   201
		{
dvander@329
   202
			return false;
dvander@324
   203
		}
dvander@324
   204
dvander@324
   205
		/**
dvander@324
   206
		 * @brief Notifies the extension that an external interface it uses is being removed.
dvander@324
   207
		 *
dvander@2134
   208
		 * @param pInterface		Pointer to interface being dropped.  This
dvander@2134
   209
		 * 							pointer may be opaque, and it should not 
dvander@2134
   210
		 *							be queried using SMInterface functions unless 
dvander@2134
   211
		 *							it can be verified to match an existing 
dvander@324
   212
		 */
dvander@324
   213
		virtual void NotifyInterfaceDrop(SMInterface *pInterface)
dvander@324
   214
		{
dvander@324
   215
		}
dvander@324
   216
dvander@324
   217
		/**
ds@755
   218
		 * @brief Return false to tell Core that your extension should be considered unusable.
dvander@324
   219
		 *
dvander@324
   220
		 * @param error				Error buffer.
dvander@324
   221
		 * @param maxlength			Size of error buffer.
dvander@324
   222
		 * @return					True on success, false otherwise.
dvander@324
   223
		 */
dvander@324
   224
		virtual bool QueryRunning(char *error, size_t maxlength)
dvander@324
   225
		{
dvander@324
   226
			return true;
dvander@324
   227
		}
dvander@324
   228
	public:
dvander@1648
   229
		/**
dvander@1648
   230
		 * @brief For extensions loaded through SourceMod, this should return true 
dvander@1648
   231
		 * if the extension needs to attach to Metamod:Source.  If the extension 
dvander@1648
   232
		 * is loaded through Metamod:Source, and uses SourceMod optionally, it must 
dvander@1648
   233
		 * return false.
dvander@1648
   234
		 *
dvander@1648
   235
		 * @return					True if Metamod:Source is needed.
dvander@1648
   236
		 */
dvander@324
   237
		virtual bool IsMetamodExtension() =0;
dvander@1648
   238
dvander@1648
   239
		/**
dvander@1648
   240
		 * @brief Must return a string containing the extension's short name.
dvander@1648
   241
		 *
dvander@1648
   242
		 * @return					String containing extension name.
dvander@1648
   243
		 */
dvander@324
   244
		virtual const char *GetExtensionName() =0;
dvander@1648
   245
dvander@1648
   246
		/**
dvander@1648
   247
		 * @brief Must return a string containing the extension's URL.
dvander@1648
   248
		 *
dvander@1648
   249
		 * @return					String containing extension URL.
dvander@1648
   250
		 */
dvander@324
   251
		virtual const char *GetExtensionURL() =0;
dvander@1648
   252
dvander@1648
   253
		/**
dvander@1648
   254
		 * @brief Must return a string containing a short identifier tag.
dvander@1648
   255
		 *
dvander@1648
   256
		 * @return					String containing extension tag.
dvander@1648
   257
		 */
dvander@324
   258
		virtual const char *GetExtensionTag() =0;
dvander@1648
   259
dvander@1648
   260
		/**
dvander@1648
   261
		 * @brief Must return a string containing a short author identifier.
dvander@1648
   262
		 *
dvander@1648
   263
		 * @return					String containing extension author.
dvander@1648
   264
		 */
dvander@324
   265
		virtual const char *GetExtensionAuthor() =0;
dvander@1648
   266
dvander@1648
   267
		/**
dvander@1648
   268
		 * @brief Must return a string containing version information.
dvander@1648
   269
		 *
dvander@1648
   270
		 * Any version string format can be used, however, SourceMod 
dvander@1648
   271
		 * makes a special guarantee version numbers in the form of 
dvander@1648
   272
		 * A.B.C.D will always be fully displayed, where:
dvander@1648
   273
		 * 
dvander@1648
   274
		 * A is a major version number of at most one digit.
dvander@1648
   275
		 * B is a minor version number of at most two digits.
dvander@1648
   276
		 * C is a minor version number of at most two digits.
dvander@1648
   277
		 * D is a build number of at most 5 digits.
dvander@1648
   278
		 *
dvander@1648
   279
		 * Thus, thirteen characters of display is guaranteed.
dvander@1648
   280
		 *
dvander@1648
   281
		 * @return					String containing extension version.
dvander@1648
   282
		 */
dvander@324
   283
		virtual const char *GetExtensionVerString() =0;
dvander@1648
   284
dvander@1648
   285
		/**
dvander@1648
   286
		 * @brief Must return a string containing description text.
dvander@1648
   287
		 *
dvander@1648
   288
		 * The description text may be longer than the other identifiers, 
dvander@1648
   289
		 * as it is only displayed when viewing one extension at a time.
dvander@1648
   290
		 * However, it should not have newlines, or any other characters 
dvander@1648
   291
		 * which would otherwise disrupt the display pattern.
dvander@1648
   292
		 * 
dvander@1648
   293
		 * @return					String containing extension description.
dvander@1648
   294
		 */
dvander@324
   295
		virtual const char *GetExtensionDescription() =0;
dvander@1648
   296
dvander@1648
   297
		/**
dvander@1648
   298
		 * @brief Must return a string containing the compilation date.
dvander@1648
   299
		 *
dvander@1648
   300
		 * @return					String containing the compilation date.
dvander@1648
   301
		 */
dvander@324
   302
		virtual const char *GetExtensionDateString() =0;
faluco@1993
   303
faluco@1993
   304
		/**
faluco@1993
   305
		 * @brief Called on server activation before plugins receive the OnServerLoad forward.
faluco@1993
   306
		 * 
faluco@1993
   307
		 * @param pEdictList		Edicts list.
faluco@1993
   308
		 * @param edictCount		Number of edicts in the list.
faluco@1993
   309
		 * @param clientMax			Maximum number of clients allowed in the server.
faluco@1993
   310
		 */
faluco@1993
   311
		virtual void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
faluco@1993
   312
		{
faluco@1993
   313
		}
dvander@324
   314
	};
dvander@324
   315
dvander@1655
   316
	/**
dvander@1655
   317
	 * @brief Returned via OnMetamodQuery() to get an IExtensionManager pointer.
dvander@1655
   318
	 */
dvander@1655
   319
	#define SOURCEMOD_INTERFACE_EXTENSIONS				"SM_ExtensionManager"
dvander@1655
   320
dvander@1655
   321
	/**
dvander@1655
   322
	 * @brief Fired through OnMetamodQuery() to notify plugins that SourceMod is 
dvander@1655
   323
	 * loaded.  
dvander@1655
   324
	 *
dvander@1655
   325
	 * Plugins should not return an interface pointer or IFACE_OK, instead, 
dvander@1655
   326
	 * they should attach as needed by searching for SOURCEMOD_INTERFACE_EXTENSIONS.
dvander@1655
   327
	 *
dvander@1655
   328
	 * This may be fired more than once; if already attached, an extension should 
dvander@1655
   329
	 * not attempt to re-attach.  The purpose of this is to notify Metamod:Source 
dvander@1655
   330
	 * plugins which load after SourceMod loads.
dvander@1655
   331
	 */
dvander@1655
   332
	#define SOURCEMOD_NOTICE_EXTENSIONS					"SM_ExtensionsAttachable"
dvander@1655
   333
dvander@324
   334
	#define SMINTERFACE_EXTENSIONMANAGER_NAME			"IExtensionManager"
dvander@1648
   335
	#define SMINTERFACE_EXTENSIONMANAGER_VERSION		2
dvander@324
   336
dvander@372
   337
	/**
dvander@372
   338
	 * @brief Manages the loading/unloading of extensions.
dvander@372
   339
	 */
dvander@324
   340
	class IExtensionManager : public SMInterface
dvander@324
   341
	{
dvander@324
   342
	public:
dvander@324
   343
		virtual const char *GetInterfaceName()
dvander@324
   344
		{
dvander@324
   345
			return SMINTERFACE_EXTENSIONMANAGER_NAME;
dvander@324
   346
		}
dvander@324
   347
		virtual unsigned int GetInterfaceVersion()
dvander@324
   348
		{
dvander@324
   349
			return SMINTERFACE_EXTENSIONMANAGER_VERSION;
dvander@324
   350
		}
dvander@1648
   351
		virtual bool IsVersionCompatible(unsigned int version)
dvander@1648
   352
		{
dvander@1648
   353
			if (version < 2)
dvander@1648
   354
			{
dvander@1648
   355
				return false;
dvander@1648
   356
			}
dvander@1648
   357
			return SMInterface::IsVersionCompatible(version);
dvander@1648
   358
		}
dvander@324
   359
	public:
dvander@324
   360
		/**
dvander@324
   361
		 * @brief Loads a extension into the extension system.
dvander@324
   362
		 *
dvander@1648
   363
		 * @param path			Path to extension file, relative to the 
dvander@1648
   364
		 *						extensions folder.
dvander@1648
   365
		 * @param error			Error buffer.
dvander@1648
   366
		 * @param maxlength		Maximum error buffer length.
dvander@1648
   367
		 * @return				New IExtension on success, NULL on failure.
dvander@1648
   368
		 *						If	NULL is returned, the error buffer will be 
dvander@1648
   369
		 *						filled with a null-terminated string.
dvander@324
   370
		 */
dvander@324
   371
		virtual IExtension *LoadExtension(const char *path, 
dvander@1648
   372
			char *error,
dvander@1648
   373
			size_t maxlength) =0;
dvander@324
   374
dvander@324
   375
		/**
dvander@1648
   376
		 * @brief Loads an extension into the extension system, directly, 
dvander@1648
   377
		 * as an external extension.  
dvander@1648
   378
		 *
dvander@1648
   379
		 * The extension receives all normal callbacks.  However, it is 
dvander@1648
   380
		 * never opened via LoadLibrary/dlopen or closed via FreeLibrary
dvander@1648
   381
		 * or dlclose.
dvander@324
   382
		 *
dvander@1648
   383
		 * @param pInterface	Pointer to an IExtensionInterface instance.
dvander@1669
   384
		 * @param filepath		Relative path to the extension's file, from 
dvander@1669
   385
		 * 						mod folder.
dvander@1648
   386
		 * @param filename		Name to use to uniquely identify the extension. 
dvander@1648
   387
		 *						The name should be generic, without any 
dvander@1648
   388
		 *						platform-specific suffices.  For example, 
dvander@1648
   389
		 *						sdktools.ext instead of sdktools.ext.so.
dvander@1648
   390
		 *						This filename is used to detect if the 
dvander@1648
   391
		 *						extension is already loaded, and to verify 
dvander@1648
   392
		 *						plugins that require the same extension.
dvander@1648
   393
		 * @param error			Buffer to store error message.
dvander@1648
   394
		 * @param maxlength		Maximum size of the error buffer.
dvander@1648
   395
		 * @return				IExtension pointer on success, NULL on failure.
dvander@1648
   396
		 *						If NULL is returned, the error buffer will be 
dvander@1648
   397
		 *						filled with a null-terminated string.
dvander@1648
   398
		 */
dvander@1648
   399
		virtual IExtension *LoadExternal(IExtensionInterface *pInterface,
dvander@1648
   400
			const char *filepath,
dvander@1648
   401
			const char *filename,
dvander@1648
   402
			char *error,
dvander@1648
   403
			size_t maxlength) =0;
dvander@1648
   404
dvander@1648
   405
		/**
dvander@1648
   406
		 * @brief Attempts to unload an extension.  External extensions must 
dvander@1648
   407
		 * call this before unloading.
dvander@1648
   408
		 *
dvander@1648
   409
		 * @param pExt			IExtension pointer.
dvander@1648
   410
		 * @return				True if successful, false otherwise.
dvander@324
   411
		 */
dvander@324
   412
		virtual bool UnloadExtension(IExtension *pExt) =0;
dvander@324
   413
	};
dvander@1649
   414
dvander@1649
   415
	#define SM_IFACEPAIR(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
dvander@1649
   416
dvander@1649
   417
	#define SM_FIND_IFACE_OR_FAIL(prefix, variable, errbuf, errsize) \
dvander@1649
   418
		if (!sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable)) \
dvander@1649
   419
		{ \
dvander@1649
   420
			if (errbuf) \
dvander@1649
   421
			{ \
dvander@1649
   422
				size_t len = snprintf(errbuf, \
dvander@1649
   423
					errsize, \
dvander@1649
   424
					"Could not find interface: %s (version: %d)", \
dvander@1649
   425
					SM_IFACEPAIR(prefix)); \
dvander@1649
   426
				if (len >= errsize) \
dvander@1649
   427
				{ \
dvander@1668
   428
					errbuf[errsize - 1] = '\0'; \
dvander@1649
   429
				} \
dvander@1649
   430
			} \
dvander@1649
   431
			return false; \
dvander@1649
   432
		}
dvander@1649
   433
dvander@1649
   434
	#define SM_FIND_IFACE(prefix, variable) \
dvander@1655
   435
		sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable);
ds@432
   436
}
dvander@324
   437
dvander@324
   438
#endif //_INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
dvander@1657
   439