1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/public/IExtensionSys.h Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,417 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#ifndef _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
1.36 +#define _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
1.37 +
1.38 +#include <IShareSys.h>
1.39 +#include <ILibrarySys.h>
1.40 +
1.41 +/**
1.42 + * @file IExtensionSys.h
1.43 + * @brief Defines the interface for loading/unloading/managing extensions.
1.44 + */
1.45 +
1.46 +namespace SourceMod
1.47 +{
1.48 + class IExtensionInterface;
1.49 + typedef void * ITERATOR; /**< Generic pointer for dependency iterators */
1.50 +
1.51 + /**
1.52 + * @brief Encapsulates an IExtensionInterface and its dependencies.
1.53 + */
1.54 + class IExtension
1.55 + {
1.56 + public:
1.57 + /**
1.58 + * @brief Returns whether or not the extension is properly loaded.
1.59 + */
1.60 + virtual bool IsLoaded() =0;
1.61 +
1.62 + /**
1.63 + * @brief Returns the extension's API interface
1.64 + *
1.65 + * @return An IExtensionInterface pointer.
1.66 + */
1.67 + virtual IExtensionInterface *GetAPI() =0;
1.68 +
1.69 + /**
1.70 + * @brief Returns the filename of the extension, relative to the
1.71 + * extension folder. If the extension is an "external" extension,
1.72 + * the file path is specified by the extension itself, and may be
1.73 + * arbitrary (not real).
1.74 + *
1.75 + * @return A string containing the extension file name.
1.76 + */
1.77 + virtual const char *GetFilename() =0;
1.78 +
1.79 + /**
1.80 + * @brief Returns the extension's identity token.
1.81 + *
1.82 + * @return An IdentityToken_t pointer.
1.83 + */
1.84 + virtual IdentityToken_t *GetIdentity() =0;
1.85 +
1.86 + /**
1.87 + * @brief Retrieves the extension dependency list for this extension.
1.88 + *
1.89 + * @param pOwner Optional pointer to store the first interface's owner.
1.90 + * @param pInterface Optional pointer to store the first interface.
1.91 + * @return An ITERATOR pointer for the results, or NULL if no results at all.
1.92 + */
1.93 + virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
1.94 +
1.95 + /**
1.96 + * @brief Finds the next dependency in the dependency list.
1.97 + *
1.98 + * @param iter Pointer to iterator from FindFirstDependency.
1.99 + * @param pOwner Optional pointer to store the interface's owner.
1.100 + * @param pInterface Optional pointer to store the interface.
1.101 + * @return True if there are more results after this, false otherwise.
1.102 + */
1.103 + virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
1.104 +
1.105 + /**
1.106 + * @brief Frees an ITERATOR handle from FindFirstDependency.
1.107 + *
1.108 + * @param iter Pointer to iterator to free.
1.109 + */
1.110 + virtual void FreeDependencyIterator(ITERATOR *iter) =0;
1.111 +
1.112 + /**
1.113 + * @brief Queries the extension to see its run state.
1.114 + *
1.115 + * @param error Error buffer (may be NULL).
1.116 + * @param maxlength Maximum length of buffer.
1.117 + * @return True if extension is okay, false if not okay.
1.118 + */
1.119 + virtual bool IsRunning(char *error, size_t maxlength) =0;
1.120 +
1.121 + /**
1.122 + * @brief Returns whether the extension is local (from the extensions
1.123 + * folder), or is from an external source (such as Metamod:Source).
1.124 + *
1.125 + * @return True if from an external source,
1.126 + * false if local to SourceMod.
1.127 + */
1.128 + virtual bool IsExternal() =0;
1.129 + };
1.130 +
1.131 + /**
1.132 + * @brief Version code of the IExtensionInterface API itself.
1.133 + *
1.134 + * Note: This is bumped when IShareSys is changed, because IShareSys
1.135 + * itself is not versioned.
1.136 + */
1.137 + #define SMINTERFACE_EXTENSIONAPI_VERSION 3
1.138 +
1.139 + /**
1.140 + * @brief The interface an extension must expose.
1.141 + */
1.142 + class IExtensionInterface
1.143 + {
1.144 + public:
1.145 + /** Returns the interface API version */
1.146 + virtual unsigned int GetExtensionVersion()
1.147 + {
1.148 + return SMINTERFACE_EXTENSIONAPI_VERSION;
1.149 + }
1.150 + public:
1.151 + /**
1.152 + * @brief Called when the extension is loaded.
1.153 + *
1.154 + * @param me Pointer back to extension.
1.155 + * @param sys Pointer to interface sharing system of SourceMod.
1.156 + * @param error Error buffer to print back to, if any.
1.157 + * @param maxlength Maximum size of error buffer.
1.158 + * @param late If this extension was loaded "late" (i.e. manually).
1.159 + * @return True if load should continue, false otherwise.
1.160 + */
1.161 + virtual bool OnExtensionLoad(IExtension *me,
1.162 + IShareSys *sys,
1.163 + char *error,
1.164 + size_t maxlength,
1.165 + bool late) =0;
1.166 +
1.167 + /**
1.168 + * @brief Called when the extension is about to be unloaded.
1.169 + */
1.170 + virtual void OnExtensionUnload() =0;
1.171 +
1.172 + /**
1.173 + * @brief Called when all extensions are loaded (loading cycle is done).
1.174 + * If loaded late, this will be called right after OnExtensionLoad().
1.175 + */
1.176 + virtual void OnExtensionsAllLoaded() =0;
1.177 +
1.178 + /**
1.179 + * @brief Called when your pause state is about to change.
1.180 + *
1.181 + * @param pause True if pausing, false if unpausing.
1.182 + */
1.183 + virtual void OnExtensionPauseChange(bool pause) =0;
1.184 +
1.185 + /**
1.186 + * @brief Asks the extension whether it's safe to remove an external
1.187 + * interface it's using. If it's not safe, return false, and the
1.188 + * extension will be unloaded afterwards.
1.189 + *
1.190 + * NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean up resources.
1.191 + *
1.192 + * @param pInterface Pointer to interface being dropped.
1.193 + * @return True to continue, false to unload this extension afterwards.
1.194 + */
1.195 + virtual bool QueryInterfaceDrop(SMInterface *pInterface)
1.196 + {
1.197 + return false;
1.198 + }
1.199 +
1.200 + /**
1.201 + * @brief Notifies the extension that an external interface it uses is being removed.
1.202 + *
1.203 + * @param pInterface Pointer to interface being dropped.
1.204 + */
1.205 + virtual void NotifyInterfaceDrop(SMInterface *pInterface)
1.206 + {
1.207 + }
1.208 +
1.209 + /**
1.210 + * @brief Return false to tell Core that your extension should be considered unusable.
1.211 + *
1.212 + * @param error Error buffer.
1.213 + * @param maxlength Size of error buffer.
1.214 + * @return True on success, false otherwise.
1.215 + */
1.216 + virtual bool QueryRunning(char *error, size_t maxlength)
1.217 + {
1.218 + return true;
1.219 + }
1.220 + public:
1.221 + /**
1.222 + * @brief For extensions loaded through SourceMod, this should return true
1.223 + * if the extension needs to attach to Metamod:Source. If the extension
1.224 + * is loaded through Metamod:Source, and uses SourceMod optionally, it must
1.225 + * return false.
1.226 + *
1.227 + * @return True if Metamod:Source is needed.
1.228 + */
1.229 + virtual bool IsMetamodExtension() =0;
1.230 +
1.231 + /**
1.232 + * @brief Must return a string containing the extension's short name.
1.233 + *
1.234 + * @return String containing extension name.
1.235 + */
1.236 + virtual const char *GetExtensionName() =0;
1.237 +
1.238 + /**
1.239 + * @brief Must return a string containing the extension's URL.
1.240 + *
1.241 + * @return String containing extension URL.
1.242 + */
1.243 + virtual const char *GetExtensionURL() =0;
1.244 +
1.245 + /**
1.246 + * @brief Must return a string containing a short identifier tag.
1.247 + *
1.248 + * @return String containing extension tag.
1.249 + */
1.250 + virtual const char *GetExtensionTag() =0;
1.251 +
1.252 + /**
1.253 + * @brief Must return a string containing a short author identifier.
1.254 + *
1.255 + * @return String containing extension author.
1.256 + */
1.257 + virtual const char *GetExtensionAuthor() =0;
1.258 +
1.259 + /**
1.260 + * @brief Must return a string containing version information.
1.261 + *
1.262 + * Any version string format can be used, however, SourceMod
1.263 + * makes a special guarantee version numbers in the form of
1.264 + * A.B.C.D will always be fully displayed, where:
1.265 + *
1.266 + * A is a major version number of at most one digit.
1.267 + * B is a minor version number of at most two digits.
1.268 + * C is a minor version number of at most two digits.
1.269 + * D is a build number of at most 5 digits.
1.270 + *
1.271 + * Thus, thirteen characters of display is guaranteed.
1.272 + *
1.273 + * @return String containing extension version.
1.274 + */
1.275 + virtual const char *GetExtensionVerString() =0;
1.276 +
1.277 + /**
1.278 + * @brief Must return a string containing description text.
1.279 + *
1.280 + * The description text may be longer than the other identifiers,
1.281 + * as it is only displayed when viewing one extension at a time.
1.282 + * However, it should not have newlines, or any other characters
1.283 + * which would otherwise disrupt the display pattern.
1.284 + *
1.285 + * @return String containing extension description.
1.286 + */
1.287 + virtual const char *GetExtensionDescription() =0;
1.288 +
1.289 + /**
1.290 + * @brief Must return a string containing the compilation date.
1.291 + *
1.292 + * @return String containing the compilation date.
1.293 + */
1.294 + virtual const char *GetExtensionDateString() =0;
1.295 + };
1.296 +
1.297 + /**
1.298 + * @brief Returned via OnMetamodQuery() to get an IExtensionManager pointer.
1.299 + */
1.300 + #define SOURCEMOD_INTERFACE_EXTENSIONS "SM_ExtensionManager"
1.301 +
1.302 + /**
1.303 + * @brief Fired through OnMetamodQuery() to notify plugins that SourceMod is
1.304 + * loaded.
1.305 + *
1.306 + * Plugins should not return an interface pointer or IFACE_OK, instead,
1.307 + * they should attach as needed by searching for SOURCEMOD_INTERFACE_EXTENSIONS.
1.308 + *
1.309 + * This may be fired more than once; if already attached, an extension should
1.310 + * not attempt to re-attach. The purpose of this is to notify Metamod:Source
1.311 + * plugins which load after SourceMod loads.
1.312 + */
1.313 + #define SOURCEMOD_NOTICE_EXTENSIONS "SM_ExtensionsAttachable"
1.314 +
1.315 + #define SMINTERFACE_EXTENSIONMANAGER_NAME "IExtensionManager"
1.316 + #define SMINTERFACE_EXTENSIONMANAGER_VERSION 2
1.317 +
1.318 + /**
1.319 + * @brief Manages the loading/unloading of extensions.
1.320 + */
1.321 + class IExtensionManager : public SMInterface
1.322 + {
1.323 + public:
1.324 + virtual const char *GetInterfaceName()
1.325 + {
1.326 + return SMINTERFACE_EXTENSIONMANAGER_NAME;
1.327 + }
1.328 + virtual unsigned int GetInterfaceVersion()
1.329 + {
1.330 + return SMINTERFACE_EXTENSIONMANAGER_VERSION;
1.331 + }
1.332 + virtual bool IsVersionCompatible(unsigned int version)
1.333 + {
1.334 + if (version < 2)
1.335 + {
1.336 + return false;
1.337 + }
1.338 + return SMInterface::IsVersionCompatible(version);
1.339 + }
1.340 + public:
1.341 + /**
1.342 + * @brief Loads a extension into the extension system.
1.343 + *
1.344 + * @param path Path to extension file, relative to the
1.345 + * extensions folder.
1.346 + * @param error Error buffer.
1.347 + * @param maxlength Maximum error buffer length.
1.348 + * @return New IExtension on success, NULL on failure.
1.349 + * If NULL is returned, the error buffer will be
1.350 + * filled with a null-terminated string.
1.351 + */
1.352 + virtual IExtension *LoadExtension(const char *path,
1.353 + char *error,
1.354 + size_t maxlength) =0;
1.355 +
1.356 + /**
1.357 + * @brief Loads an extension into the extension system, directly,
1.358 + * as an external extension.
1.359 + *
1.360 + * The extension receives all normal callbacks. However, it is
1.361 + * never opened via LoadLibrary/dlopen or closed via FreeLibrary
1.362 + * or dlclose.
1.363 + *
1.364 + * @param pInterface Pointer to an IExtensionInterface instance.
1.365 + * @param filepath Relative path to the extension's file, from
1.366 + * mod folder.
1.367 + * @param filename Name to use to uniquely identify the extension.
1.368 + * The name should be generic, without any
1.369 + * platform-specific suffices. For example,
1.370 + * sdktools.ext instead of sdktools.ext.so.
1.371 + * This filename is used to detect if the
1.372 + * extension is already loaded, and to verify
1.373 + * plugins that require the same extension.
1.374 + * @param error Buffer to store error message.
1.375 + * @param maxlength Maximum size of the error buffer.
1.376 + * @return IExtension pointer on success, NULL on failure.
1.377 + * If NULL is returned, the error buffer will be
1.378 + * filled with a null-terminated string.
1.379 + */
1.380 + virtual IExtension *LoadExternal(IExtensionInterface *pInterface,
1.381 + const char *filepath,
1.382 + const char *filename,
1.383 + char *error,
1.384 + size_t maxlength) =0;
1.385 +
1.386 + /**
1.387 + * @brief Attempts to unload an extension. External extensions must
1.388 + * call this before unloading.
1.389 + *
1.390 + * @param pExt IExtension pointer.
1.391 + * @return True if successful, false otherwise.
1.392 + */
1.393 + virtual bool UnloadExtension(IExtension *pExt) =0;
1.394 + };
1.395 +
1.396 + #define SM_IFACEPAIR(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
1.397 +
1.398 + #define SM_FIND_IFACE_OR_FAIL(prefix, variable, errbuf, errsize) \
1.399 + if (!sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable)) \
1.400 + { \
1.401 + if (errbuf) \
1.402 + { \
1.403 + size_t len = snprintf(errbuf, \
1.404 + errsize, \
1.405 + "Could not find interface: %s (version: %d)", \
1.406 + SM_IFACEPAIR(prefix)); \
1.407 + if (len >= errsize) \
1.408 + { \
1.409 + errbuf[errsize - 1] = '\0'; \
1.410 + } \
1.411 + } \
1.412 + return false; \
1.413 + }
1.414 +
1.415 + #define SM_FIND_IFACE(prefix, variable) \
1.416 + sharesys->RequestInterface(SM_IFACEPAIR(prefix), myself, (SMInterface **)&variable);
1.417 +}
1.418 +
1.419 +#endif //_INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
1.420 +