core/logic/PluginSys.h
author Nicholas Hastings <skamonkey@gmail.com>
Wed May 21 17:25:30 2014 -0400 (2014-05-21)
changeset 4377 7a44be5b7162
parent 4065 0f85577d23ee
permissions -rw-r--r--
Trigger build for hl2sdk-l4d changes.
dvander@370
     1
/**
dvander@4065
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@3099
     5
 * Copyright (C) 2004-2010 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@370
     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@1231
    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@1231
    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@1231
    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@370
    28
 *
dvander@370
    29
 * Version: $Id$
dvander@370
    30
 */
dvander@370
    31
dvander@173
    32
#ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
dvander@173
    33
#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
dvander@173
    34
dvander@211
    35
#include <time.h>
faluco@333
    36
#include <errno.h>
faluco@333
    37
#include <sys/stat.h>
dvander@173
    38
#include <IPluginSys.h>
dvander@220
    39
#include <IHandleSys.h>
ds@611
    40
#include <IForwardSys.h>
dvander@174
    41
#include <sh_list.h>
dvander@174
    42
#include <sh_stack.h>
faluco@389
    43
#include <sh_vector.h>
dvander@601
    44
#include <sh_string.h>
dvander@3872
    45
#include "common_logic.h"
dvander@309
    46
#include <IRootConsoleMenu.h>
dvander@4065
    47
#include <sm_stringhashmap.h>
dvander@4065
    48
#include <sm_namehashset.h>
dvander@2042
    49
#include "ITranslator.h"
asherkin@3601
    50
#include "IGameConfigs.h"
dvander@2086
    51
#include "NativeOwner.h"
dvander@2086
    52
#include "ShareSys.h"
dvander@173
    53
dvander@2547
    54
class CPlayer;
dvander@2547
    55
dvander@174
    56
using namespace SourceHook;
dvander@174
    57
dvander@209
    58
/**
dvander@209
    59
 * NOTES:
dvander@209
    60
 *
dvander@1923
    61
 * UPDATE 2008-03-11: These comments are horribly out of date.  They paint a good overall 
dvander@1923
    62
 * picture of how PluginSys works, but things like dependencies and fake natives have 
dvander@1923
    63
 * complicated things quite a bit.
dvander@1923
    64
 *
dvander@209
    65
 *  Currently this system needs a lot of work but it's good skeletally.  Plugin creation 
dvander@209
    66
 * is done without actually compiling anything.  This is done by Load functions in the 
dvander@209
    67
 * manager.  This will need a rewrite when we add context switching.
dvander@209
    68
 *
dvander@209
    69
 *  The plugin object itself has a few things to note.  The most important is that it stores
dvander@209
    70
 * a table of function objects.  The manager marshals allocation and freeing of these objects.
dvander@209
    71
 * The plugin object can be in erroneous states, they are:
dvander@209
    72
 *   Plugin_Error   --> Some error occurred any time during or after compilation.
dvander@209
    73
 *						This error can be cleared since the plugin itself is valid.
dvander@209
    74
 *						However, the state itself being set prevents any runtime action.
dvander@209
    75
 *   Plugin_BadLoad	--> The plugin failed to load entirely and nothing can be done to save it.
dvander@209
    76
 *
dvander@209
    77
 *  If a plugin fails to load externally, it is never added to the internal tracker.  However, 
dvander@209
    78
 * plugins that failed to load from the internal loading mechanism are always tracked.  This 
dvander@209
    79
 * allows users to see which automatically loaded plugins failed, and makes the interface a bit
dvander@209
    80
 * more flexible.
dvander@211
    81
 *
dvander@211
    82
 *  Once a plugin is compiled, it sets its own state to Plugin_Created.  This state is still invalid
dvander@211
    83
 * for execution.  SourceMod is a two pass system, and even though the second pass is not implemented
dvander@211
    84
 * yet, it is structured so Plugin_Created must be switched to Plugin_Running in the second pass.  When
dvander@211
    85
 * implemented, a Created plugin will be switched to Error in the second pass if it not loadable.
dvander@211
    86
 *
dvander@211
    87
 *  The two pass loading mechanism is described below.  Modules/natives are not implemented yet.
dvander@211
    88
 * PASS ONE: All loadable plugins are found and have the following steps performed:
dvander@211
    89
 *			 1.  Loading and compilation is attempted.
dvander@211
    90
 *			 2.  If successful, all natives from Core are added.
dvander@211
    91
 *			 3.  OnPluginLoad() is called.
dvander@211
    92
 *			 4.  If failed, any user natives are scrapped and the process halts here.
dvander@211
    93
 *			 5.  If successful, the plugin is ready for Pass 2.
dvander@211
    94
 * INTERMEDIATE:
dvander@211
    95
 *			 1.  All forced modules are loaded.
dvander@211
    96
 * PASS TWO: All loaded plugins are found and have these steps performed:
dvander@211
    97
 *			 1. Any modules referenced in the plugin that are not already loaded, are loaded.
dvander@211
    98
 *			 2. If any module fails to load and the plugin requires it, load fails and jump to step 6.
dvander@211
    99
 *			 3. If any natives are unresolved, check if they are found in the user-natives pool.
dvander@211
   100
 *			 4. If yes, load succeeds.  If not, natives are passed through a native acceptance filter.
dvander@211
   101
 *			 5. If the filter fails, the plugin is marked as failed.
dvander@211
   102
 *			 6. If the plugin has failed to load at this point, any dynamic natives it has added are scrapped.
dvander@211
   103
 *			    Furthermore, any plugin that referenced these natives must now have pass 2 re-ran.
dvander@211
   104
 * PASS THREE (not a real pass):
ds@426
   105
 *			 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
dvander@209
   106
 */
dvander@209
   107
faluco@383
   108
enum LoadRes
faluco@383
   109
{
faluco@383
   110
	LoadRes_Successful,
faluco@383
   111
	LoadRes_AlreadyLoaded,
dvander@1436
   112
	LoadRes_Failure,
fyrenmoo@2675
   113
	LoadRes_SilentFailure,
dvander@1436
   114
	LoadRes_NeverLoad
faluco@383
   115
};
faluco@383
   116
fyrenmoo@2675
   117
enum APLRes
fyrenmoo@2675
   118
{
fyrenmoo@2675
   119
	APLRes_Success,
fyrenmoo@2675
   120
	APLRes_Failure,
fyrenmoo@2675
   121
	APLRes_SilentFailure
fyrenmoo@2675
   122
};
fyrenmoo@2675
   123
dvander@2086
   124
class CPlugin : 
dvander@3872
   125
	public SMPlugin,
dvander@2086
   126
	public CNativeOwner
dvander@173
   127
{
dvander@174
   128
	friend class CPluginManager;
dvander@176
   129
	friend class CFunction;
dvander@173
   130
public:
dvander@209
   131
	CPlugin(const char *file);
dvander@209
   132
	~CPlugin();
dvander@209
   133
public:
faluco@641
   134
	PluginType GetType();
faluco@641
   135
	SourcePawn::IPluginContext *GetBaseContext();
faluco@641
   136
	sp_context_t *GetContext();
dvander@2193
   137
	void *GetPluginStructure();
faluco@641
   138
	const char *GetFilename();
faluco@641
   139
	bool IsDebugging();
faluco@641
   140
	PluginStatus GetStatus();
fyrenmoo@2675
   141
	bool IsSilentlyFailed();
fyrenmoo@2675
   142
	void SetSilentlyFailed(bool sf);
dvander@2193
   143
	const sm_plugininfo_t *GetPublicInfo();
faluco@641
   144
	bool SetPauseState(bool paused);
faluco@641
   145
	unsigned int GetSerial();
faluco@641
   146
	IdentityToken_t *GetIdentity();
dvander@1766
   147
	unsigned int CalcMemUsage();
faluco@641
   148
	bool SetProperty(const char *prop, void *ptr);
faluco@641
   149
	bool GetProperty(const char *prop, void **ptr, bool remove=false);
dvander@2086
   150
	void DropEverything();
dvander@2193
   151
	SourcePawn::IPluginRuntime *GetRuntime();
dvander@3872
   152
	CNativeOwner *ToNativeOwner() {
dvander@3872
   153
		return this;
dvander@3872
   154
	}
dvander@173
   155
public:
dvander@209
   156
	/**
dvander@209
   157
	 * Creates a plugin object with default values.
dvander@209
   158
	 *   If an error buffer is specified, and an error occurs, the error will be copied to the buffer
dvander@209
   159
	 * and NULL will be returned.
dvander@209
   160
	 *   If an error buffer is not specified, the error will be copied to an internal buffer and 
dvander@209
   161
	 * a valid (but error-stated) CPlugin will be returned.
dvander@209
   162
	 */
dvander@209
   163
	static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
dvander@4065
   164
dvander@4065
   165
	static inline bool matches(const char *file, const CPlugin *plugin)
dvander@4065
   166
	{
dvander@4065
   167
		return strcmp(plugin->m_filename, file) == 0;
dvander@4065
   168
	}
dvander@209
   169
public:
dvander@229
   170
dvander@209
   171
	/**
dvander@209
   172
	 * Sets an error state on the plugin
dvander@209
   173
	 */
dvander@209
   174
	void SetErrorState(PluginStatus status, const char *error_fmt, ...);
dvander@211
   175
dvander@211
   176
	/**
dvander@229
   177
	 * Initializes the plugin's identity information
dvander@229
   178
	 */
dvander@229
   179
	void InitIdentity();
dvander@229
   180
dvander@229
   181
	/**
dvander@211
   182
	 * Calls the OnPluginLoad function, and sets any failed states if necessary.
dvander@211
   183
	 * NOTE: Valid pre-states are: Plugin_Created
dvander@282
   184
	 * NOTE: If validated, plugin state is changed to Plugin_Loaded
dvander@211
   185
	 *
dvander@211
   186
	 * If the error buffer is NULL, the error message is cached locally.
dvander@211
   187
	 */
fyrenmoo@2675
   188
	APLRes Call_AskPluginLoad(char *error, size_t maxlength);
dvander@211
   189
dvander@211
   190
	/**
ds@426
   191
	 * Calls the OnPluginStart function.
dvander@211
   192
	 * NOTE: Valid pre-states are: Plugin_Created
dvander@282
   193
	 * NOTE: Post-state will be Plugin_Running
dvander@211
   194
	 */
ds@426
   195
	void Call_OnPluginStart();
dvander@282
   196
dvander@282
   197
	/**
ds@426
   198
	 * Calls the OnPluginEnd function.
dvander@282
   199
	 */
ds@426
   200
	void Call_OnPluginEnd();
faluco@290
   201
faluco@290
   202
	/**
faluco@1221
   203
	 * Calls the OnAllPluginsLoaded function.
faluco@1221
   204
	 */
faluco@1221
   205
	void Call_OnAllPluginsLoaded();
faluco@1221
   206
faluco@1221
   207
	/**
dvander@315
   208
	 * Returns true if a plugin is usable.
dvander@315
   209
	 */
dvander@615
   210
	bool IsRunnable();
faluco@389
   211
faluco@389
   212
	/**
dvander@2042
   213
	 * Get languages info.
dvander@536
   214
	 */
dvander@2042
   215
	IPhraseCollection *GetPhrases();
dvander@211
   216
public:
faluco@333
   217
	/**
dvander@536
   218
	 * Returns the modification time during last plugin load.
dvander@536
   219
	 */
dvander@615
   220
	time_t GetTimeStamp();
faluco@333
   221
faluco@333
   222
	/**
dvander@536
   223
	 * Returns the current modification time of the plugin file.
dvander@536
   224
	 */
faluco@333
   225
	time_t GetFileTimeStamp();
dvander@282
   226
dvander@282
   227
	/** 
dvander@282
   228
	 * Returns true if the plugin was running, but is now invalid.
dvander@282
   229
	 */
dvander@282
   230
	bool WasRunning();
dvander@536
   231
dvander@536
   232
	Handle_t GetMyHandle();
dvander@978
   233
dvander@2086
   234
	bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
dvander@978
   235
	void AddConfig(bool autoCreate, const char *cfg, const char *folder);
dvander@3879
   236
	size_t GetConfigCount();
dvander@3879
   237
	AutoConfig *GetConfig(size_t i);
faluco@1112
   238
	inline void AddLibrary(const char *name)
faluco@1089
   239
	{
faluco@1112
   240
		m_Libraries.push_back(name);
faluco@1089
   241
	}
asherkin@3703
   242
	void LibraryActions(LibraryAction action);
dvander@2342
   243
	void SyncMaxClients(int max_clients);
dvander@173
   244
protected:
dvander@2342
   245
	bool UpdateInfo();
faluco@333
   246
	void SetTimeStamp(time_t t);
dvander@605
   247
	void DependencyDropped(CPlugin *pOwner);
dvander@173
   248
private:
dvander@174
   249
	PluginType m_type;
ds@652
   250
	char m_filename[PLATFORM_MAX_PATH];
dvander@173
   251
	PluginStatus m_status;
fyrenmoo@2675
   252
	bool m_bSilentlyFailed;
dvander@173
   253
	unsigned int m_serial;
dvander@173
   254
	sm_plugininfo_t m_info;
dvander@209
   255
	char m_errormsg[256];
dvander@211
   256
	time_t m_LastAccess;
dvander@229
   257
	IdentityToken_t *m_ident;
dvander@220
   258
	Handle_t m_handle;
dvander@282
   259
	bool m_WasRunning;
dvander@2042
   260
	IPhraseCollection *m_pPhrases;
faluco@1112
   261
	List<String> m_RequiredLibs;
faluco@1112
   262
	List<String> m_Libraries;
dvander@4065
   263
	StringHashMap<void *> m_Props;
dvander@605
   264
	bool m_FakeNativesMissing;
faluco@1112
   265
	bool m_LibraryMissing;
dvander@978
   266
	CVector<AutoConfig *> m_configs;
dvander@1630
   267
	bool m_bGotAllLoaded;
dvander@2105
   268
	int m_FileVersion;
dvander@2105
   269
	char m_DateTime[256];
dvander@2193
   270
	IPluginRuntime *m_pRuntime;
dvander@2193
   271
	IPluginContext *m_pContext;
dvander@2342
   272
	sp_pubvar_t *m_MaxClientsVar;
dvander@601
   273
};
dvander@601
   274
dvander@220
   275
class CPluginManager : 
dvander@3872
   276
	public IScriptManager,
dvander@220
   277
	public SMGlobalClass,
dvander@309
   278
	public IHandleTypeDispatch,
dvander@309
   279
	public IRootConsoleCommand
dvander@174
   280
{
dvander@176
   281
	friend class CPlugin;
dvander@174
   282
public:
dvander@174
   283
	CPluginManager();
dvander@176
   284
	~CPluginManager();
dvander@174
   285
public:
dvander@203
   286
	/* Implements iterator class */
dvander@174
   287
	class CPluginIterator : public IPluginIterator
dvander@174
   288
	{
dvander@174
   289
	public:
dvander@213
   290
		CPluginIterator(List<CPlugin *> *mylist);
dvander@174
   291
		virtual ~CPluginIterator();
dvander@174
   292
		virtual bool MorePlugins();
dvander@174
   293
		virtual IPlugin *GetPlugin();
dvander@174
   294
		virtual void NextPlugin();
dvander@282
   295
		void Release();
dvander@174
   296
	public:
dvander@174
   297
		void Reset();
dvander@174
   298
	private:
dvander@213
   299
		List<CPlugin *> *mylist;
dvander@213
   300
		List<CPlugin *>::iterator current;
dvander@174
   301
	};
dvander@174
   302
	friend class CPluginManager::CPluginIterator;
dvander@3872
   303
public: //IScriptManager
dvander@282
   304
	IPlugin *LoadPlugin(const char *path, 
dvander@174
   305
								bool debug,
dvander@174
   306
								PluginType type,
dvander@174
   307
								char error[],
ds@755
   308
								size_t maxlength,
faluco@383
   309
								bool *wasloaded);
dvander@282
   310
	bool UnloadPlugin(IPlugin *plugin);
dvander@282
   311
	IPlugin *FindPluginByContext(const sp_context_t *ctx);
dvander@282
   312
	unsigned int GetPluginCount();
dvander@282
   313
	IPluginIterator *GetPluginIterator();
dvander@282
   314
	void AddPluginsListener(IPluginsListener *listener);
dvander@282
   315
	void RemovePluginsListener(IPluginsListener *listener);
dvander@3872
   316
	void LoadAll(const char *config_path, const char *plugins_path);
dvander@3872
   317
	void RefreshAll();
dvander@3872
   318
	SMPlugin *FindPluginByOrder(unsigned num) {
dvander@3872
   319
		return GetPluginByOrder(num);
dvander@3872
   320
	}
dvander@3872
   321
	SMPlugin *FindPluginByIdentity(IdentityToken_t *ident) {
dvander@3872
   322
		return GetPluginFromIdentity(ident);
dvander@3872
   323
	}
dvander@3872
   324
	SMPlugin *FindPluginByContext(IPluginContext *ctx) {
dvander@3872
   325
		return GetPluginByCtx(ctx->GetContext());
dvander@3872
   326
	}
dvander@3872
   327
	SMPlugin *FindPluginByContext(sp_context_t *ctx) {
dvander@3872
   328
		return GetPluginByCtx(ctx);
dvander@3872
   329
	}
dvander@3872
   330
	SMPlugin *FindPluginByConsoleArg(const char *text);
dvander@3872
   331
	SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) {
dvander@3872
   332
		return static_cast<SMPlugin *>(PluginFromHandle(hndl, errp));
dvander@3872
   333
	}
dvander@3881
   334
	const CVector<SMPlugin *> *ListPlugins();
dvander@3881
   335
	void FreePluginList(const CVector<SMPlugin *> *plugins);
dvander@220
   336
public: //SMGlobalClass
dvander@282
   337
	void OnSourceModAllInitialized();
dvander@282
   338
	void OnSourceModShutdown();
asherkin@3601
   339
	ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
dvander@2342
   340
	void OnSourceModMaxPlayersChanged(int newvalue);
dvander@220
   341
public: //IHandleTypeDispatch
dvander@282
   342
	void OnHandleDestroy(HandleType_t type, void *object);
dvander@1766
   343
	bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
dvander@309
   344
public: //IRootConsoleCommand
faluco@1541
   345
	void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
dvander@190
   346
public:
dvander@203
   347
	/**
dvander@211
   348
	 * Loads all plugins not yet loaded
dvander@203
   349
	 */
dvander@211
   350
	void LoadAll_FirstPass(const char *config, const char *basedir);
dvander@211
   351
dvander@211
   352
	/**
dvander@211
   353
	 * Runs the second loading pass for all plugins
dvander@211
   354
	 */
dvander@211
   355
	void LoadAll_SecondPass();
dvander@203
   356
dvander@203
   357
	/**
dvander@203
   358
	 * Tests a plugin file mask against a local folder.
dvander@203
   359
	 * The alias is searched backwards from localdir - i.e., given this input:
dvander@203
   360
	 *   csdm/ban        csdm/ban
dvander@203
   361
	 *   ban             csdm/ban
dvander@203
   362
	 *   csdm/ban        optional/csdm/ban
dvander@203
   363
	 * All of these will return true for an alias match.  
dvander@203
   364
	 * Wildcards are allowed in the filename.
dvander@203
   365
	 */
dvander@209
   366
	bool TestAliasMatch(const char *alias, const char *localdir);
dvander@211
   367
dvander@211
   368
	/** 
dvander@211
   369
	 * Returns whether anything loaded will be a late load.
dvander@211
   370
	 */
faluco@290
   371
	bool IsLateLoadTime() const;
dvander@233
   372
dvander@233
   373
	/**
dvander@247
   374
	 * Converts a Handle to an IPlugin if possible.
dvander@247
   375
	 */
dvander@247
   376
	IPlugin *PluginFromHandle(Handle_t handle, HandleError *err);
faluco@290
   377
faluco@290
   378
	/**
dvander@309
   379
	 * Finds a plugin based on its index. (starts on index 1)
dvander@309
   380
	 */
faluco@290
   381
	CPlugin *GetPluginByOrder(int num);
dvander@309
   382
dvander@1638
   383
	int GetOrderOfPlugin(IPlugin *pl);
dvander@1638
   384
ds@457
   385
	/** 
ds@457
   386
	 * Internal version of FindPluginByContext()
ds@457
   387
	 */
dvander@2193
   388
	CPlugin *GetPluginByCtx(const sp_context_t *ctx);
ds@457
   389
dvander@309
   390
	/**
dvander@309
   391
	 * Gets status text for a status code 
dvander@309
   392
	 */
dvander@309
   393
	const char *GetStatusText(PluginStatus status);
dvander@315
   394
faluco@333
   395
	/**
ds@611
   396
	 * Add public functions from all running or paused
ds@611
   397
	 * plugins to the specified forward if the names match.
ds@611
   398
	 */
ds@611
   399
	void AddFunctionsToForward(const char *name, IChangeableForward *pForward);
ds@611
   400
faluco@1221
   401
	/**
faluco@1221
   402
	 * Iterates through plugins to call OnAllPluginsLoaded.
faluco@1221
   403
	 */
faluco@1221
   404
	void AllPluginsLoaded();
faluco@1221
   405
dvander@900
   406
	CPlugin *GetPluginFromIdentity(IdentityToken_t *pToken);
dvander@900
   407
dvander@1018
   408
	void Shutdown();
dvander@1018
   409
asherkin@3703
   410
	void OnLibraryAction(const char *lib, LibraryAction action);
dvander@1124
   411
dvander@1124
   412
	bool LibraryExists(const char *lib);
faluco@1348
   413
faluco@1348
   414
	bool ReloadPlugin(CPlugin *pl);
dvander@1630
   415
dvander@1630
   416
	void UnloadAll();
dvander@1902
   417
dvander@2342
   418
	void SyncMaxClients(int max_clients);
dvander@2547
   419
dvander@2547
   420
	void ListPluginsToClient(CPlayer *player, const CCommand &args);
dvander@209
   421
private:
ds@755
   422
	LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength);
dvander@298
   423
dvander@298
   424
	void LoadAutoPlugin(const char *plugin);
dvander@298
   425
dvander@209
   426
	/**
dvander@209
   427
	 * Recursively loads all plugins in the given directory.
dvander@209
   428
	 */
dvander@209
   429
	void LoadPluginsFromDir(const char *basedir, const char *localdir);
dvander@209
   430
dvander@209
   431
	/**
dvander@211
   432
	 * Adds a plugin object.  This is wrapped by LoadPlugin functions.
dvander@211
   433
	 */
dvander@211
   434
	void AddPlugin(CPlugin *pPlugin);
dvander@211
   435
dvander@211
   436
	/**
dvander@211
   437
	 * Runs the second loading pass on a plugin.
dvander@209
   438
	 */
dvander@298
   439
	bool RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength);
dvander@211
   440
dvander@211
   441
	/**
dvander@315
   442
	 * Runs an extension pass on a plugin.
dvander@315
   443
	 */
dvander@315
   444
	bool LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength);
faluco@430
   445
faluco@1112
   446
	/**
faluco@1112
   447
	* Manages required natives.
faluco@1112
   448
	*/
faluco@1112
   449
	bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength);
faluco@1112
   450
faluco@430
   451
	void _SetPauseState(CPlugin *pPlugin, bool pause);
dvander@174
   452
protected:
dvander@209
   453
	/**
dvander@209
   454
	 * Caching internal objects
dvander@209
   455
	 */
dvander@174
   456
	void ReleaseIterator(CPluginIterator *iter);
dvander@900
   457
public:
dvander@229
   458
	inline IdentityToken_t *GetIdentity()
dvander@229
   459
	{
dvander@229
   460
		return m_MyIdent;
dvander@229
   461
	}
dvander@3872
   462
	IPluginManager *GetOldAPI();
dvander@601
   463
private:
faluco@1112
   464
	void TryRefreshDependencies(CPlugin *pOther);
dvander@174
   465
private:
dvander@174
   466
	List<IPluginsListener *> m_listeners;
dvander@213
   467
	List<CPlugin *> m_plugins;
dvander@174
   468
	CStack<CPluginManager::CPluginIterator *> m_iters;
dvander@4065
   469
	NameHashSet<CPlugin *> m_LoadLookup;
dvander@211
   470
	bool m_AllPluginsLoaded;
dvander@229
   471
	IdentityToken_t *m_MyIdent;
dvander@601
   472
dvander@601
   473
	/* Dynamic native stuff */
dvander@601
   474
	List<FakeNative *> m_Natives;
dvander@601
   475
dvander@1630
   476
	bool m_LoadingLocked;
asherkin@3601
   477
	
asherkin@3601
   478
	// Config
asherkin@3601
   479
	bool m_bBlockBadPlugins;
asherkin@3703
   480
	
asherkin@3703
   481
	// Forwards
asherkin@3703
   482
	IForward *m_pOnLibraryAdded;
asherkin@3703
   483
	IForward *m_pOnLibraryRemoved;
dvander@174
   484
};
dvander@174
   485
dvander@211
   486
extern CPluginManager g_PluginSys;
dvander@174
   487
dvander@173
   488
#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
dvander@2906
   489