1 #ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
2 #define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
5 #include <IPluginSys.h>
8 #include "sm_globals.h"
10 #include "PluginInfoDatabase.h"
13 using namespace SourceHook;
18 * Currently this system needs a lot of work but it's good skeletally. Plugin creation
19 * is done without actually compiling anything. This is done by Load functions in the
20 * manager. This will need a rewrite when we add context switching.
22 * The plugin object itself has a few things to note. The most important is that it stores
23 * a table of function objects. The manager marshals allocation and freeing of these objects.
24 * The plugin object can be in erroneous states, they are:
25 * Plugin_Error --> Some error occurred any time during or after compilation.
26 * This error can be cleared since the plugin itself is valid.
27 * However, the state itself being set prevents any runtime action.
28 * Plugin_BadLoad --> The plugin failed to load entirely and nothing can be done to save it.
30 * If a plugin fails to load externally, it is never added to the internal tracker. However,
31 * plugins that failed to load from the internal loading mechanism are always tracked. This
32 * allows users to see which automatically loaded plugins failed, and makes the interface a bit
35 * Once a plugin is compiled, it sets its own state to Plugin_Created. This state is still invalid
36 * for execution. SourceMod is a two pass system, and even though the second pass is not implemented
37 * yet, it is structured so Plugin_Created must be switched to Plugin_Running in the second pass. When
38 * implemented, a Created plugin will be switched to Error in the second pass if it not loadable.
40 * The two pass loading mechanism is described below. Modules/natives are not implemented yet.
41 * PASS ONE: All loadable plugins are found and have the following steps performed:
42 * 1. Loading and compilation is attempted.
43 * 2. If successful, all natives from Core are added.
44 * 3. OnPluginLoad() is called.
45 * 4. If failed, any user natives are scrapped and the process halts here.
46 * 5. If successful, the plugin is ready for Pass 2.
48 * 1. All forced modules are loaded.
49 * PASS TWO: All loaded plugins are found and have these steps performed:
50 * 1. Any modules referenced in the plugin that are not already loaded, are loaded.
51 * 2. If any module fails to load and the plugin requires it, load fails and jump to step 6.
52 * 3. If any natives are unresolved, check if they are found in the user-natives pool.
53 * 4. If yes, load succeeds. If not, natives are passed through a native acceptance filter.
54 * 5. If the filter fails, the plugin is marked as failed.
55 * 6. If the plugin has failed to load at this point, any dynamic natives it has added are scrapped.
56 * Furthermore, any plugin that referenced these natives must now have pass 2 re-ran.
57 * PASS THREE (not a real pass):
58 * 7. Once all plugins are deemed to be loaded, OnPluginInit() is called
61 #define SM_CONTEXTVAR_MYSELF 0
65 ContextPair() : base(NULL), ctx(NULL), co(NULL)
74 class CPlugin : public IPlugin
76 friend class CPluginManager;
77 friend class CFunction;
79 CPlugin(const char *file);
82 virtual PluginType GetType() const;
83 virtual SourcePawn::IPluginContext *GetBaseContext() const;
84 virtual sp_context_t *GetContext() const;
85 virtual const sm_plugininfo_t *GetPublicInfo() const;
86 virtual const char *GetFilename() const;
87 virtual bool IsDebugging() const;
88 virtual PluginStatus GetStatus() const;
89 virtual bool SetPauseState(bool paused);
90 virtual unsigned int GetSerial() const;
91 virtual const sp_plugin_t *GetPluginStructure() const;
92 virtual IPluginFunction *GetFunctionByName(const char *public_name);
93 virtual IPluginFunction *GetFunctionById(funcid_t func_id);
96 * Creates a plugin object with default values.
97 * If an error buffer is specified, and an error occurs, the error will be copied to the buffer
98 * and NULL will be returned.
99 * If an error buffer is not specified, the error will be copied to an internal buffer and
100 * a valid (but error-stated) CPlugin will be returned.
102 static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
105 * Starts the initial compilation of a plugin.
106 * Returns false if another compilation exists or there is a current context set.
108 ICompilation *StartMyCompile(IVirtualMachine *vm);
110 * Finalizes a compilation. If error buffer is NULL, the error is saved locally.
112 bool FinishMyCompile(char *error, size_t maxlength);
113 void CancelMyCompile();
115 * Sets an error state on the plugin
117 void SetErrorState(PluginStatus status, const char *error_fmt, ...);
120 * Calls the OnPluginLoad function, and sets any failed states if necessary.
121 * NOTE: Valid pre-states are: Plugin_Created
122 * If validated, plugin state is changed to Plugin_Loaded
124 * If the error buffer is NULL, the error message is cached locally.
126 bool Call_AskPluginLoad(char *error, size_t maxlength);
129 * Calls the OnPluginInit function.
130 * NOTE: Valid pre-states are: Plugin_Created
131 * NOTE: Pre-state will be changed to Plugin_Running
133 void Call_OnPluginInit();
135 time_t HasUpdatedFile();
141 char m_filename[PLATFORM_MAX_PATH+1];
142 PluginStatus m_status;
143 unsigned int m_serial;
144 sm_plugininfo_t m_info;
145 sp_plugin_t *m_plugin;
146 unsigned int m_funcsnum;
147 CFunction **m_priv_funcs;
148 CFunction **m_pub_funcs;
149 char m_errormsg[256];
153 class CPluginManager : public IPluginManager
155 friend class CPlugin;
160 /* Implements iterator class */
161 class CPluginIterator : public IPluginIterator
164 CPluginIterator(List<CPlugin *> *mylist);
165 virtual ~CPluginIterator();
166 virtual bool MorePlugins();
167 virtual IPlugin *GetPlugin();
168 virtual void NextPlugin();
169 virtual void Release();
173 List<CPlugin *> *mylist;
174 List<CPlugin *>::iterator current;
176 friend class CPluginManager::CPluginIterator;
177 public: //IPluginManager
178 virtual IPlugin *LoadPlugin(const char *path,
183 virtual bool UnloadPlugin(IPlugin *plugin);
184 virtual IPlugin *FindPluginByContext(const sp_context_t *ctx);
185 virtual unsigned int GetPluginCount();
186 virtual IPluginIterator *GetPluginIterator();
187 virtual void AddPluginsListener(IPluginsListener *listener);
188 virtual void RemovePluginsListener(IPluginsListener *listener);
191 * Loads all plugins not yet loaded
193 void LoadAll_FirstPass(const char *config, const char *basedir);
196 * Runs the second loading pass for all plugins
198 void LoadAll_SecondPass();
201 * Tests a plugin file mask against a local folder.
202 * The alias is searched backwards from localdir - i.e., given this input:
205 * csdm/ban optional/csdm/ban
206 * All of these will return true for an alias match.
207 * Wildcards are allowed in the filename.
209 bool TestAliasMatch(const char *alias, const char *localdir);
212 * Registers natives in core itself ONLY.
214 void RegisterGlobalNatives(sp_nativeinfo_t *info[]);
217 * Returns whether anything loaded will be a late load.
219 bool IsLateLoadTime();
222 * Recursively loads all plugins in the given directory.
224 void LoadPluginsFromDir(const char *basedir, const char *localdir);
227 * Loads a plugin using automatic information.
228 * The file must be relative to the plugins folder.
230 void LoadAutoPlugin(const char *file);
233 * Adds a plugin object. This is wrapped by LoadPlugin functions.
235 void AddPlugin(CPlugin *pPlugin);
238 * Runs the second loading pass on a plugin.
240 void RunSecondPass(CPlugin *pPlugin);
243 * Adds any globally registered natives to a plugin
245 void AddCoreNativesToPlugin(CPlugin *pPlugin);
248 * Caching internal objects
250 void ReleaseIterator(CPluginIterator *iter);
251 CFunction *GetFunctionFromPool(funcid_t f, CPlugin *plugin);
252 void ReleaseFunctionToPool(CFunction *func);
254 List<IPluginsListener *> m_listeners;
255 List<CPlugin *> m_plugins;
256 List<sp_nativeinfo_t *> m_natives;
257 CStack<CPluginManager::CPluginIterator *> m_iters;
258 CStack<CFunction *> m_funcpool;
259 CPluginInfoDatabase m_PluginInfo;
261 bool m_AllPluginsLoaded;
264 extern CPluginManager g_PluginSys;
266 #endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_