00001 /** 00002 * vim: set ts=4 : 00003 * ============================================================================= 00004 * SourceMod 00005 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. 00006 * ============================================================================= 00007 * 00008 * This program is free software; you can redistribute it and/or modify it under 00009 * the terms of the GNU General Public License, version 3.0, as published by the 00010 * Free Software Foundation. 00011 * 00012 * This program is distributed in the hope that it will be useful, but WITHOUT 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00014 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00015 * details. 00016 * 00017 * You should have received a copy of the GNU General Public License along with 00018 * this program. If not, see <http://www.gnu.org/licenses/>. 00019 * 00020 * As a special exception, AlliedModders LLC gives you permission to link the 00021 * code of this program (as well as its derivative works) to "Half-Life 2," the 00022 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software 00023 * by the Valve Corporation. You must obey the GNU General Public License in 00024 * all respects for all other code used. Additionally, AlliedModders LLC grants 00025 * this exception to all derivative works. AlliedModders LLC defines further 00026 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), 00027 * or <http://www.sourcemod.net/license.php>. 00028 * 00029 * Version: $Id: IExtensionSys.h 2315 2008-07-01 06:12:16Z dvander $ 00030 */ 00031 00032 #ifndef _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_ 00033 #define _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_ 00034 00035 #include <IShareSys.h> 00036 #include <ILibrarySys.h> 00037 00038 /** 00039 * @file IExtensionSys.h 00040 * @brief Defines the interface for loading/unloading/managing extensions. 00041 */ 00042 00043 struct edict_t; 00044 00045 namespace SourceMod 00046 { 00047 class IExtensionInterface; 00048 typedef void * ITERATOR; /**< Generic pointer for dependency iterators */ 00049 00050 /** 00051 * @brief Encapsulates an IExtensionInterface and its dependencies. 00052 */ 00053 class IExtension 00054 { 00055 public: 00056 /** 00057 * @brief Returns whether or not the extension is properly loaded. 00058 */ 00059 virtual bool IsLoaded() =0; 00060 00061 /** 00062 * @brief Returns the extension's API interface 00063 * 00064 * @return An IExtensionInterface pointer. 00065 */ 00066 virtual IExtensionInterface *GetAPI() =0; 00067 00068 /** 00069 * @brief Returns the filename of the extension, relative to the 00070 * extension folder. If the extension is an "external" extension, 00071 * the file path is specified by the extension itself, and may be 00072 * arbitrary (not real). 00073 * 00074 * @return A string containing the extension file name. 00075 */ 00076 virtual const char *GetFilename() =0; 00077 00078 /** 00079 * @brief Returns the extension's identity token. 00080 * 00081 * @return An IdentityToken_t pointer. 00082 */ 00083 virtual IdentityToken_t *GetIdentity() =0; 00084 00085 /** 00086 * @brief Retrieves the extension dependency list for this extension. 00087 * 00088 * @param pOwner Optional pointer to store the first interface's owner. 00089 * @param pInterface Optional pointer to store the first interface. 00090 * @return An ITERATOR pointer for the results, or NULL if no results at all. 00091 */ 00092 virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0; 00093 00094 /** 00095 * @brief Finds the next dependency in the dependency list. 00096 * 00097 * @param iter Pointer to iterator from FindFirstDependency. 00098 * @param pOwner Optional pointer to store the interface's owner. 00099 * @param pInterface Optional pointer to store the interface. 00100 * @return True if there are more results after this, false otherwise. 00101 */ 00102 virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0; 00103 00104 /** 00105 * @brief Frees an ITERATOR handle from FindFirstDependency. 00106 * 00107 * @param iter Pointer to iterator to free. 00108 */ 00109 virtual void FreeDependencyIterator(ITERATOR *iter) =0; 00110 00111 /** 00112 * @brief Queries the extension to see its run state. 00113 * 00114 * @param error Error buffer (may be NULL). 00115 * @param maxlength Maximum length of buffer. 00116 * @return True if extension is okay, false if not okay. 00117 */ 00118 virtual bool IsRunning(char *error, size_t maxlength) =0; 00119 00120 /** 00121 * @brief Returns whether the extension is local (from the extensions 00122 * folder), or is from an external source (such as Metamod:Source). 00123 * 00124 * @return True if from an external source, 00125 * false if local to SourceMod. 00126 */ 00127 virtual bool IsExternal() =0; 00128 }; 00129 00130 /** 00131 * @brief Version code of the IExtensionInterface API itself. 00132 * 00133 * Note: This is bumped when IShareSys is changed, because IShareSys 00134 * itself is not versioned. 00135 */ 00136 #define SMINTERFACE_EXTENSIONAPI_VERSION 4 00137 00138 /** 00139 * @brief The interface an extension must expose. 00140 */ 00141 class IExtensionInterface 00142 { 00143 public: 00144 /** Returns the interface API version */ 00145 virtual unsigned int GetExtensionVersion() 00146 { 00147 return SMINTERFACE_EXTENSIONAPI_VERSION; 00148 } 00149 public: 00150 /** 00151 * @brief Called when the extension is loaded. 00152 * 00153 * @param me Pointer back to extension. 00154 * @param sys Pointer to interface sharing system of SourceMod. 00155 * @param error Error buffer to print back to, if any. 00156 * @param maxlength Maximum size of error buffer. 00157 * @param late If this extension was loaded "late" (i.e. manually). 00158 * @return True if load should continue, false otherwise. 00159 */ 00160 virtual bool OnExtensionLoad(IExtension *me, 00161 IShareSys *sys, 00162 char *error, 00163 size_t maxlength, 00164 bool late) =0; 00165 00166 /** 00167 * @brief Called when the extension is about to be unloaded. 00168 */ 00169 virtual void OnExtensionUnload() =0; 00170 00171 /** 00172 * @brief Called when all extensions are loaded (loading cycle is done). 00173 * If loaded late, this will be called right after OnExtensionLoad(). 00174 */ 00175 virtual void OnExtensionsAllLoaded() =0; 00176 00177 /** 00178 * @brief Called when your pause state is about to change. 00179 * 00180 * @param pause True if pausing, false if unpausing. 00181 */ 00182 virtual void OnExtensionPauseChange(bool pause) =0; 00183 00184 /** 00185 * @brief Asks the extension whether it's safe to remove an external 00186 * interface it's using. If it's not safe, return false, and the 00187 * extension will be unloaded afterwards. 00188 * 00189 * NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean 00190 * up resources. 00191 * 00192 * @param pInterface Pointer to interface being dropped. This 00193 * pointer may be opaque, and it should not 00194 * be queried using SMInterface functions unless 00195 * it can be verified to match an existing 00196 * pointer of known type. 00197 * @return True to continue, false to unload this 00198 * extension afterwards. 00199 */ 00200 virtual bool QueryInterfaceDrop(SMInterface *pInterface) 00201 { 00202 return false; 00203 } 00204 00205 /** 00206 * @brief Notifies the extension that an external interface it uses is being removed. 00207 * 00208 * @param pInterface Pointer to interface being dropped. This 00209 * pointer may be opaque, and it should not 00210 * be queried using SMInterface functions unless 00211 * it can be verified to match an existing 00212 */ 00213 virtual void NotifyInterfaceDrop(SMInterface *pInterface) 00214 { 00215 } 00216 00217 /** 00218 * @brief Return false to tell Core that your extension should be considered unusable. 00219 * 00220 * @param error Error buffer. 00221 * @param maxlength Size of error buffer. 00222 * @return True on success, false otherwise. 00223 */ 00224 virtual bool QueryRunning(char *error, size_t maxlength) 00225 { 00226 return true; 00227 } 00228 public: 00229 /** 00230 * @brief For extensions loaded through SourceMod, this should return true 00231 * if the extension needs to attach to Metamod:Source. If the extension 00232 * is loaded through Metamod:Source, and uses SourceMod optionally, it must 00233 * return false. 00234 * 00235 * @return True if Metamod:Source is needed. 00236 */ 00237 virtual bool IsMetamodExtension() =0; 00238 00239 /** 00240 * @brief Must return a string containing the extension's short name. 00241 * 00242 * @return String containing extension name. 00243 */ 00244 virtual const char *GetExtensionName() =0; 00245 00246 /** 00247 * @brief Must return a string containing the extension's URL. 00248 * 00249 * @return String containing extension URL. 00250 */ 00251 virtual const char *GetExtensionURL() =0; 00252 00253 /** 00254 * @brief Must return a string containing a short identifier tag. 00255 * 00256 * @return String containing extension tag. 00257 */ 00258 virtual const char *GetExtensionTag() =0; 00259 00260 /** 00261 * @brief Must return a string containing a short author identifier. 00262 * 00263 * @return String containing extension author. 00264 */ 00265 virtual const char *GetExtensionAuthor() =0; 00266 00267 /** 00268 * @brief Must return a string containing version information. 00269 * 00270 * Any version string format can be used, however, SourceMod 00271 * makes a special guarantee version numbers in the form of 00272 * A.B.C.D will always be fully displayed, where: 00273 * 00274 * A is a major version number of at most one digit. 00275 * B is a minor version number of at most two digits. 00276 * C is a minor version number of at most two digits. 00277 * D is a build number of at most 5 digits. 00278 * 00279 * Thus, thirteen characters of display is guaranteed. 00280 * 00281 * @return String containing extension version. 00282 */ 00283 virtual const char *GetExtensionVerString() =0; 00284 00285 /** 00286 * @brief Must return a string containing description text. 00287 * 00288 * The description text may be longer than the other identifiers, 00289 * as it is only displayed when viewing one extension at a time. 00290 * However, it should not have newlines, or any other characters 00291 * which would otherwise disrupt the display pattern. 00292 * 00293 * @return String containing extension description. 00294 */ 00295 virtual const char *GetExtensionDescription() =0; 00296 00297 /** 00298 * @brief Must return a string containing the compilation date. 00299 * 00300 * @return String containing the compilation date. 00301 */ 00302 virtual const char *GetExtensionDateString() =0; 00303 00304 /** 00305 * @brief Called on server activation before plugins receive the OnServerLoad forward. 00306 * 00307 * @param pEdictList Edicts list. 00308 * @param edictCount Number of edicts in the list. 00309 * @param clientMax Maximum number of clients allowed in the server. 00310 */ 00311 virtual void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) 00312 { 00313 } 00314 }; 00315 00316 /** 00317 * @brief Returned via OnMetamodQuery() to get an IExtensionManager pointer. 00318 */ 00319 #define SOURCEMOD_INTERFACE_EXTENSIONS "SM_ExtensionManager" 00320 00321 /** 00322 * @brief Fired through OnMetamodQuery() to notify plugins that SourceMod is 00323 * loaded. 00324 * 00325 * Plugins should not return an interface pointer or IFACE_OK, instead, 00326 * they should attach as needed by searching for SOURCEMOD_INTERFACE_EXTENSIONS. 00327 * 00328 * This may be fired more than once; if already attached, an extension should 00329 * not attempt to re-attach. The purpose of this is to notify Metamod:Source 00330 * plugins which load after SourceMod loads. 00331 */ 00332 #define SOURCEMOD_NOTICE_EXTENSIONS "SM_ExtensionsAttachable" 00333 00334 #define SMINTERFACE_EXTENSIONMANAGER_NAME "IExtensionManager" 00335 #define SMINTERFACE_EXTENSIONMANAGER_VERSION 2 00336 00337 /** 00338 * @brief Manages the loading/unloading of extensions. 00339 */ 00340 class IExtensionManager : public SMInterface 00341 { 00342 public: 00343 virtual const char *GetInterfaceName() 00344 { 00345 return SMINTERFACE_EXTENSIONMANAGER_NAME; 00346 } 00347 virtual unsigned int GetInterfaceVersion() 00348 { 00349 return SMINTERFACE_EXTENSIONMANAGER_VERSION; 00350 } 00351 virtual bool IsVersionCompatible(unsigned int version) 00352 { 00353 if (version < 2) 00354 { 00355 return false; 00356 } 00357 return SMInterface::IsVersionCompatible(version); 00358 } 00359 public: 00360 /** 00361 * @brief Loads a extension into the extension system. 00362 * 00363 * @param path Path to extension file, relative to the 00364 * extensions folder. 00365 * @param error Error buffer. 00366 * @param maxlength Maximum error buffer length. 00367 * @return New IExtension on success, NULL on failure. 00368 * If NULL is returned, the error buffer will be 00369 * filled with a null-terminated string. 00370 */ 00371 virtual IExtension *LoadExtension(const char *path, 00372 char *error, 00373 size_t maxlength) =0; 00374 00375 /** 00376 * @brief Loads an extension into the extension system, directly, 00377 * as an external extension. 00378 * 00379 * The extension receives all normal callbacks. However, it is 00380 * never opened via LoadLibrary/dlopen or closed via FreeLibrary 00381 * or dlclose. 00382 * 00383 * @param pInterface Pointer to an IExtensionInterface instance. 00384 * @param filepath Relative path to the extension's file, from 00385 * mod folder. 00386 * @param filename Name to use to uniquely identify the extension. 00387 * The name should be generic, without any 00388 * platform-specific suffices. For example, 00389 * sdktools.ext instead of sdktools.ext.so. 00390 * This filename is used to detect if the 00391 * extension is already loaded, and to verify 00392 * plugins that require the same extension. 00393 * @param error Buffer to store error message. 00394 * @param maxlength Maximum size of the error buffer. 00395 * @return IExtension pointer on success, NULL on failure. 00396 * If NULL is returned, the error buffer will be 00397 * filled with a null-terminated string. 00398 */ 00399 virtual IExtension *LoadExternal(IExtensionInterface *pInterface, 00400 const char *filepath, 00401 const char *filename, 00402 char *error, 00403 size_t maxlength) =0; 00404 00405 /** 00406 * @brief Attempts to unload an extension. External extensions must 00407 * call this before unloading. 00408 * 00409 * @param pExt IExtension pointer. 00410 * @return True if successful, false otherwise. 00411 */ 00412 virtual bool UnloadExtension(IExtension *pExt) =0; 00413 }; 00414 00415 #define SM_IFACEPAIR(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION 00416 00417 #define SM_FIND_IFACE_OR_FAIL(prefix, variable, errbuf, errsize) \ 00418 if (!sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable)) \ 00419 { \ 00420 if (errbuf) \ 00421 { \ 00422 size_t len = snprintf(errbuf, \ 00423 errsize, \ 00424 "Could not find interface: %s (version: %d)", \ 00425 SM_IFACEPAIR(prefix)); \ 00426 if (len >= errsize) \ 00427 { \ 00428 errbuf[errsize - 1] = '\0'; \ 00429 } \ 00430 } \ 00431 return false; \ 00432 } 00433 00434 #define SM_FIND_IFACE(prefix, variable) \ 00435 sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable); 00436 } 00437 00438 #endif //_INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_ 00439
1.5.1