public/IExtensionSys.h
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 08:02:24 2007 +0000 (2007-10-28)
changeset 1648 3c8256da48b9
parent 1572 adbc41dc9cd0
child 1649 37373aea4dfe
permissions -rw-r--r--
added experimental extension interface for loading external extensions from mm:s
hard-bumped the extension api
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     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 #ifndef _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
    33 #define _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
    34 
    35 #include <IShareSys.h>
    36 #include <ILibrarySys.h>
    37 
    38 /**
    39  * @file IExtensionSys.h
    40  * @brief Defines the interface for loading/unloading/managing extensions.
    41  */
    42 
    43 namespace SourceMod
    44 {
    45 	class IExtensionInterface;
    46 	typedef void *		ITERATOR;		/**< Generic pointer for dependency iterators */
    47 
    48 	/** 
    49 	 * @brief Encapsulates an IExtensionInterface and its dependencies.
    50 	 */
    51 	class IExtension
    52 	{
    53 	public:
    54 		/**
    55 		 * @brief Returns whether or not the extension is properly loaded.
    56 		 */
    57 		virtual bool IsLoaded() =0;
    58 
    59 		/**
    60 		 * @brief Returns the extension's API interface
    61 		 *
    62 		 * @return			An IExtensionInterface pointer.
    63 		 */
    64 		virtual IExtensionInterface *GetAPI() =0;
    65 
    66 		/**
    67 		 * @brief Returns the filename of the extension, relative to the
    68 		 * extension folder.   If the extension is an "external" extension, 
    69 		 * the file path is specified by the extension itself, and may be 
    70 		 * arbitrary (not real).
    71 		 *
    72 		 * @return			A string containing the extension file name.
    73 		 */
    74 		virtual const char *GetFilename() =0;
    75 
    76 		/**
    77 		 * @brief Returns the extension's identity token.
    78 		 *
    79 		 * @return			An IdentityToken_t pointer.
    80 		 */
    81 		virtual IdentityToken_t *GetIdentity() =0;
    82 
    83 		/**
    84 		 * @brief Retrieves the extension dependency list for this extension.
    85 		 *
    86 		 * @param pOwner		Optional pointer to store the first interface's owner.
    87 		 * @param pInterface	Optional pointer to store the first interface.
    88 		 * @return				An ITERATOR pointer for the results, or NULL if no results at all.
    89 		 */
    90 		virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
    91 
    92 		/**
    93 		 * @brief Finds the next dependency in the dependency list.
    94 		 *
    95 		 * @param iter			Pointer to iterator from FindFirstDependency.
    96 		 * @param pOwner		Optional pointer to store the interface's owner.
    97 		 * @param pInterface	Optional pointer to store the interface.
    98 		 * @return				True if there are more results after this, false otherwise.
    99 		 */
   100 		virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
   101 
   102 		/**
   103 		 * @brief Frees an ITERATOR handle from FindFirstDependency.
   104 		 *
   105 		 * @param iter			Pointer to iterator to free.
   106 		 */
   107 		virtual void FreeDependencyIterator(ITERATOR *iter) =0;
   108 
   109 		/**
   110 		 * @brief Queries the extension to see its run state.
   111 		 *
   112 		 * @param error			Error buffer (may be NULL).
   113 		 * @param maxlength		Maximum length of buffer.
   114 		 * @return				True if extension is okay, false if not okay.
   115 		 */
   116 		virtual bool IsRunning(char *error, size_t maxlength) =0;
   117 
   118 		/**
   119 		 * @brief Returns whether the extension is local (from the extensions 
   120 		 * folder), or is from an external source (such as Metamod:Source).
   121 		 *
   122 		 * @return				True if from an external source, 
   123 		 *						false if local to SourceMod.
   124 		 */
   125 		virtual bool IsExternal() =0;
   126 	};
   127 
   128 	/**
   129 	 * @brief Version code of the IExtensionInterface API itself.
   130 	 */
   131 	#define SMINTERFACE_EXTENSIONAPI_VERSION	2
   132 
   133 	/**
   134 	 * @brief The interface an extension must expose.
   135 	 */
   136 	class IExtensionInterface
   137 	{
   138 	public:
   139 		/** Returns the interface API version */
   140 		virtual unsigned int GetExtensionVersion()
   141 		{
   142 			return SMINTERFACE_EXTENSIONAPI_VERSION;
   143 		}
   144 	public:
   145 		/**
   146 		 * @brief Called when the extension is loaded.
   147 		 * 
   148 		 * @param me		Pointer back to extension.
   149 		 * @param sys		Pointer to interface sharing system of SourceMod.
   150 		 * @param error		Error buffer to print back to, if any.
   151 		 * @param maxlength	Maximum size of error buffer.
   152 		 * @param late		If this extension was loaded "late" (i.e. manually).
   153 		 * @return			True if load should continue, false otherwise.
   154 		 */
   155 		virtual bool OnExtensionLoad(IExtension *me,
   156 			IShareSys *sys, 
   157 			char *error, 
   158 			size_t maxlength, 
   159 			bool late) =0;
   160 
   161 		/**
   162 		 * @brief Called when the extension is about to be unloaded.
   163 		 */
   164 		virtual void OnExtensionUnload() =0;
   165 
   166 		/**
   167 		 * @brief Called when all extensions are loaded (loading cycle is done).
   168 		 * If loaded late, this will be called right after OnExtensionLoad().
   169 		 */
   170 		virtual void OnExtensionsAllLoaded() =0;
   171 
   172 		/**
   173 		 * @brief Called when your pause state is about to change.
   174 		 * 
   175 		 * @param pause		True if pausing, false if unpausing.
   176 		 */
   177 		virtual void OnExtensionPauseChange(bool pause) =0;
   178 
   179 		/**
   180 		 * @brief Asks the extension whether it's safe to remove an external 
   181 		 * interface it's using.  If it's not safe, return false, and the 
   182 		 * extension will be unloaded afterwards.
   183 		 *
   184 		 * NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean up resources.
   185 		 *
   186 		 * @param pInterface		Pointer to interface being dropped.
   187 		 * @return					True to continue, false to unload this extension afterwards.
   188 		 */
   189 		virtual bool QueryInterfaceDrop(SMInterface *pInterface)
   190 		{
   191 			return false;
   192 		}
   193 
   194 		/**
   195 		 * @brief Notifies the extension that an external interface it uses is being removed.
   196 		 *
   197 		 * @param pInterface		Pointer to interface being dropped.
   198 		 */
   199 		virtual void NotifyInterfaceDrop(SMInterface *pInterface)
   200 		{
   201 		}
   202 
   203 		/**
   204 		 * @brief Return false to tell Core that your extension should be considered unusable.
   205 		 *
   206 		 * @param error				Error buffer.
   207 		 * @param maxlength			Size of error buffer.
   208 		 * @return					True on success, false otherwise.
   209 		 */
   210 		virtual bool QueryRunning(char *error, size_t maxlength)
   211 		{
   212 			return true;
   213 		}
   214 	public:
   215 		/**
   216 		 * @brief For extensions loaded through SourceMod, this should return true 
   217 		 * if the extension needs to attach to Metamod:Source.  If the extension 
   218 		 * is loaded through Metamod:Source, and uses SourceMod optionally, it must 
   219 		 * return false.
   220 		 *
   221 		 * @return					True if Metamod:Source is needed.
   222 		 */
   223 		virtual bool IsMetamodExtension() =0;
   224 
   225 		/**
   226 		 * @brief Must return a string containing the extension's short name.
   227 		 *
   228 		 * @return					String containing extension name.
   229 		 */
   230 		virtual const char *GetExtensionName() =0;
   231 
   232 		/**
   233 		 * @brief Must return a string containing the extension's URL.
   234 		 *
   235 		 * @return					String containing extension URL.
   236 		 */
   237 		virtual const char *GetExtensionURL() =0;
   238 
   239 		/**
   240 		 * @brief Must return a string containing a short identifier tag.
   241 		 *
   242 		 * @return					String containing extension tag.
   243 		 */
   244 		virtual const char *GetExtensionTag() =0;
   245 
   246 		/**
   247 		 * @brief Must return a string containing a short author identifier.
   248 		 *
   249 		 * @return					String containing extension author.
   250 		 */
   251 		virtual const char *GetExtensionAuthor() =0;
   252 
   253 		/**
   254 		 * @brief Must return a string containing version information.
   255 		 *
   256 		 * Any version string format can be used, however, SourceMod 
   257 		 * makes a special guarantee version numbers in the form of 
   258 		 * A.B.C.D will always be fully displayed, where:
   259 		 * 
   260 		 * A is a major version number of at most one digit.
   261 		 * B is a minor version number of at most two digits.
   262 		 * C is a minor version number of at most two digits.
   263 		 * D is a build number of at most 5 digits.
   264 		 *
   265 		 * Thus, thirteen characters of display is guaranteed.
   266 		 *
   267 		 * @return					String containing extension version.
   268 		 */
   269 		virtual const char *GetExtensionVerString() =0;
   270 
   271 		/**
   272 		 * @brief Must return a string containing description text.
   273 		 *
   274 		 * The description text may be longer than the other identifiers, 
   275 		 * as it is only displayed when viewing one extension at a time.
   276 		 * However, it should not have newlines, or any other characters 
   277 		 * which would otherwise disrupt the display pattern.
   278 		 * 
   279 		 * @return					String containing extension description.
   280 		 */
   281 		virtual const char *GetExtensionDescription() =0;
   282 
   283 		/**
   284 		 * @brief Must return a string containing the compilation date.
   285 		 *
   286 		 * @return					String containing the compilation date.
   287 		 */
   288 		virtual const char *GetExtensionDateString() =0;
   289 	};
   290 
   291 	#define SMINTERFACE_EXTENSIONMANAGER_NAME			"IExtensionManager"
   292 	#define SMINTERFACE_EXTENSIONMANAGER_VERSION		2
   293 
   294 	/**
   295 	 * @brief Manages the loading/unloading of extensions.
   296 	 */
   297 	class IExtensionManager : public SMInterface
   298 	{
   299 	public:
   300 		virtual const char *GetInterfaceName()
   301 		{
   302 			return SMINTERFACE_EXTENSIONMANAGER_NAME;
   303 		}
   304 		virtual unsigned int GetInterfaceVersion()
   305 		{
   306 			return SMINTERFACE_EXTENSIONMANAGER_VERSION;
   307 		}
   308 		virtual bool IsVersionCompatible(unsigned int version)
   309 		{
   310 			if (version < 2)
   311 			{
   312 				return false;
   313 			}
   314 			return SMInterface::IsVersionCompatible(version);
   315 		}
   316 	public:
   317 		/**
   318 		 * @brief Loads a extension into the extension system.
   319 		 *
   320 		 * @param path			Path to extension file, relative to the 
   321 		 *						extensions folder.
   322 		 * @param lifetime		Lifetime of the extension (currently ignored).
   323 		 * @param error			Error buffer.
   324 		 * @param maxlength		Maximum error buffer length.
   325 		 * @return				New IExtension on success, NULL on failure.
   326 		 *						If	NULL is returned, the error buffer will be 
   327 		 *						filled with a null-terminated string.
   328 		 */
   329 		virtual IExtension *LoadExtension(const char *path, 
   330 			char *error,
   331 			size_t maxlength) =0;
   332 
   333 		/**
   334 		 * @brief Loads an extension into the extension system, directly, 
   335 		 * as an external extension.  
   336 		 *
   337 		 * The extension receives all normal callbacks.  However, it is 
   338 		 * never opened via LoadLibrary/dlopen or closed via FreeLibrary
   339 		 * or dlclose.
   340 		 *
   341 		 * @param pInterface	Pointer to an IExtensionInterface instance.
   342 		 * @param filepath		Absolute path to the extension's file.
   343 		 * @param filename		Name to use to uniquely identify the extension. 
   344 		 *						The name should be generic, without any 
   345 		 *						platform-specific suffices.  For example, 
   346 		 *						sdktools.ext instead of sdktools.ext.so.
   347 		 *						This filename is used to detect if the 
   348 		 *						extension is already loaded, and to verify 
   349 		 *						plugins that require the same extension.
   350 		 * @param error			Buffer to store error message.
   351 		 * @param maxlength		Maximum size of the error buffer.
   352 		 * @return				IExtension pointer on success, NULL on failure.
   353 		 *						If NULL is returned, the error buffer will be 
   354 		 *						filled with a null-terminated string.
   355 		 */
   356 		virtual IExtension *LoadExternal(IExtensionInterface *pInterface,
   357 			const char *filepath,
   358 			const char *filename,
   359 			char *error,
   360 			size_t maxlength) =0;
   361 
   362 		/**
   363 		 * @brief Attempts to unload an extension.  External extensions must 
   364 		 * call this before unloading.
   365 		 *
   366 		 * @param pExt			IExtension pointer.
   367 		 * @return				True if successful, false otherwise.
   368 		 */
   369 		virtual bool UnloadExtension(IExtension *pExt) =0;
   370 	};
   371 }
   372 
   373 #endif //_INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_