1 /** @file plugins.h  Plugin loader.
2  *
3  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  * @authors Copyright © 2006-2015 Daniel Swanson <danij@dengine.net>
5  *
6  * @par License
7  * GPL: http://www.gnu.org/licenses/gpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details. You should have received a copy of the GNU
16  * General Public License along with this program; if not, see:
17  * http://www.gnu.org/licenses</small>
18  */
19 
20 #ifndef LIBDOOMSDAY_PLUGINS_H
21 #define LIBDOOMSDAY_PLUGINS_H
22 
23 #include <de/str.h>
24 #include <de/rect.h>
25 #include "world/valuetype.h"
26 
27 /**
28  * Unique identifier assigned to each plugin during initial startup.
29  * Zero is not a valid ID.
30  */
31 typedef int pluginid_t;
32 
33 typedef int (*pluginfunc_t) (void);
34 typedef int (*hookfunc_t) (int type, int parm, void *data);
35 
36 /// Maximum allowed number of plugins.
37 /// @todo Remove fixed size limit.
38 #define MAX_PLUGS   32
39 
40 /// Hook types.
41 typedef enum {
42     HOOK_STARTUP = 0,               ///< Called ASAP after startup.
43     HOOK_INIT = 1,                  ///< Called after engine has been initialized.
44     HOOK_DEFS = 2,                  ///< Called after DEDs have been loaded.
45     HOOK_MAP_CONVERT = 3,           ///< Called when a map needs converting.
46     HOOK_TICKER = 4,                ///< Called as part of the run loop.
47     HOOK_DEMO_STOP = 5,             ///< Called when demo playback completes.
48     HOOK_FINALE_SCRIPT_BEGIN = 6,   ///< Called as a script begins.
49     HOOK_FINALE_SCRIPT_STOP = 7,    ///< Called as a script stops.
50     HOOK_FINALE_SCRIPT_TICKER = 8,  ///< Called each time a script 'thinks'.
51     HOOK_FINALE_EVAL_IF = 9,        ///< Called to evaluate an IF conditional statement.
52     HOOK_VIEWPORT_RESHAPE = 10,     ///< Called when viewport dimensions change.
53     HOOK_SAVEGAME_CONVERT = 11,     ///< Called when a legacy savegame needs converting.
54     HOOK_GAME_INIT = 12,            /**< Called when initializing a loaded game. This occurs
55                                          once all startup resources are loaded but @em before
56                                          parsing of definitions and processing game data.
57                                          This is a suitable time for game data conversion. */
58     HOOK_MAPINFO_CONVERT = 13,      ///< Called when map definition data needs converting.
59 
60     NUM_HOOK_TYPES
61 } HookType;
62 
63 /// Parameters for HOOK_FINALE_EVAL_IF
64 typedef struct {
65     char const *token;
66     dd_bool     returnVal;
67 } ddhook_finale_script_evalif_paramaters_t;
68 
69 /// Parameters for HOOK_FINALE_SCRIPT_TICKER
70 typedef struct {
71     dd_bool runTick;
72     dd_bool canSkip;
73 } ddhook_finale_script_ticker_paramaters_t;
74 
75 /// Parameters for HOOK_VIEWPORT_RESHAPE
76 typedef struct {
77     RectRaw geometry;     ///< New/Current.
78     RectRaw oldGeometry;  ///< Previous.
79 } ddhook_viewport_reshape_t;
80 
81 /// Parameters for HOOK_SAVEGAME_CONVERT
82 typedef struct {
83     Str sourcePath;
84     Str outputPath;
85     Str fallbackGameId;
86 } ddhook_savegame_convert_t;
87 
88 /// Parameters for HOOK_MAPINFO_CONVERT
89 typedef struct {
90     Str paths;            ///< ';' delimited
91     Str translated;
92     Str translatedCustom;
93 } ddhook_mapinfo_convert_t;
94 
95 /// Parameters for DD_NOTIFY_PLAYER_WEAPON_CHANGED
96 typedef struct {
97     int player;
98     int weapon;             ///< Number of the weapon.
99     char const *weaponId;   ///< Defined in Values (includes power-ups) (UTF-8).
100 } ddnotify_player_weapon_changed_t;
101 
102 /// Parameters for DD_NOTIFY_PSPRITE_STATE_CHANGED
103 typedef struct {
104     int player;
105     struct state_s const *state;
106 } ddnotify_psprite_state_changed_t;
107 
108 #ifdef __cplusplus
109 
110 #include <de/Observers>
111 #include <de/Info>
112 #include "libdoomsday.h"
113 #include "library.h"
114 #include "gameapi.h"
115 
116 /**
117  * Routines exported from a game plugin. @ingroup game
118  *
119  * Note that this struct is not part of the game plugin ABI any longer (since 2.1).
120  */
121 struct GameExports
122 {
123     // Base-level.
124     void        (*PreInit) (char const *gameId);
125     void        (*PostInit) (void);
126     dd_bool     (*TryShutdown) (void);
127     void        (*Shutdown) (void);
128     void        (*UpdateState) (int step);
129     int         (*GetInteger) (int id);
130     void       *(*GetPointer) (int id);
131 
132     // Networking.
133     int         (*NetServerStart) (int before);
134     int         (*NetServerStop) (int before);
135     int         (*NetConnect) (int before);
136     int         (*NetDisconnect) (int before);
137     long int    (*NetPlayerEvent) (int playernum, int type, void *data);
138     int         (*NetWorldEvent) (int type, int parm, void *data);
139     void        (*HandlePacket) (int fromplayer, int type, void *data,
140                                  size_t length);
141 
142     // Tickers.
143     void        (*Ticker) (timespan_t ticLength);
144 
145     // Responders.
146     int         (*FinaleResponder) (void const *ddev);
147     int         (*PrivilegedResponder) (struct event_s *ev);
148     int         (*Responder) (struct event_s *ev);
149     int         (*FallbackResponder) (struct event_s *ev);
150 
151     // Refresh.
152     void        (*BeginFrame) (void);
153 
154     /**
155      * Called at the end of a refresh frame. This is the last chance the game
156      * will have at updating the engine state before rendering of the frame
157      * begins. Once rendering begins, the viewer can still be updated however
158      * any changes will not take effect until the subsequent frame. Therefore
159      * this is the place where games should strive to update the viewer to
160      * ensure latency-free world refresh.
161      */
162     void        (*EndFrame) (void);
163 
164     /**
165      * Draw the view port display of the identified console @a player.
166      * The engine will configure a orthographic GL projection in real pixel
167      * dimensions prior to calling this.
168      *
169      * Example subdivision of the game window into four view ports:
170      * <pre>
171      *     (0,0)-----------------------. X
172      *       | .--------. |            |
173      *       | | window | |            |
174      *       | '--------' |            |
175      *       |    port #0 |    port #1 |
176      *       |-------------------------|
177      *       |            |            |
178      *       |            |            |
179      *       |            |            |
180      *       |    port #2 |    port #3 |
181      *       '--------------------(xn-1, yn-1)
182      *       Y               Game Window
183      * </pre>
184      *
185      * @param port  Logical number of this view port.
186      * @param portGeometry  Geometry of the view port in real screen pixels.
187      * @param windowGeometry  Geometry of the view window within the port, in
188      *                        real screen pixels.
189      *
190      * @param player  Console player number associated with the view port.
191      * @param layer  Logical layer identifier for the content to be drawn:
192      *      - 0: The bottom-most layer and the one which generally contains the
193      *        call to R_RenderPlayerView.
194      *      - 1: Displays to be drawn on top of view window (after bordering),
195      *        such as the player HUD.
196      */
197     void        (*DrawViewPort) (int port, RectRaw const *portGeometry,
198                                  RectRaw const *windowGeometry, int player, int layer);
199 
200     /**
201      * Draw over-viewport displays covering the whole game window. Typically
202      * graphical user interfaces such as game menus are done here.
203      *
204      * @param windowSize  Dimensions of the game window in real screen pixels.
205      */
206     void        (*DrawWindow) (Size2Raw const *windowSize);
207 
208     // Miscellaneous.
209     void        (*MobjThinker) (void *mobj);
210     coord_t     (*MobjFriction) (struct mobj_s const *mobj);  // Returns a friction factor.
211     dd_bool     (*MobjCheckPositionXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z);
212     dd_bool     (*MobjTryMoveXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z);
213     de::String  (*MobjStateAsInfo) (struct mobj_s const *);
214     void        (*MobjRestoreState) (struct mobj_s *, de::Info::BlockElement const &stateInfoBlockElement);
215 
216     void        (*SectorHeightChangeNotification)(int sectorIdx);  // Applies necessary checks on objects.
217 
218     // Map setup
219 
220     /**
221      * Called once a map change (i.e., P_MapChange()) has completed to allow the
222      * game to do any post change finalization it needs to do at this time.
223      */
224     void        (*FinalizeMapChange) (void const *uri);
225 
226     /**
227      * Called when trying to assign a value read from the map data (to a
228      * property known to us) that we don't know what to do with.
229      *
230      * (eg the side->toptexture field contains a text string that
231      * we don't understand but the game might).
232      *
233      * @return The action code returned by the game depends on the context.
234      */
235     int         (*HandleMapDataPropertyValue) (uint id, int dtype, int prop,
236                                                valuetype_t type, void *data);
237     // Post map setup
238     /**
239      * The engine calls this to inform the game of any changes it is
240      * making to map data object to which the game might want to
241      * take further action.
242      */
243     int         (*HandleMapObjectStatusReport) (int code, uint id, int dtype, void *data);
244 };
245 
246 /**
247  * Plugin loader.
248  */
249 class LIBDOOMSDAY_PUBLIC Plugins
250 {
251 public:
252     DENG2_DEFINE_AUDIENCE2(PublishAPI,   void publishAPIToPlugin(Library *))
253     DENG2_DEFINE_AUDIENCE2(Notification, void pluginSentNotification(int id, void *data))
254 
255     DENG2_ERROR(EntryPointError);
256 
257 public:
258     Plugins();
259 
260     void publishAPIs(Library *lib);
261 
262     void notify(int notification, void *data);
263 
264     /**
265      * Loads all the plugins from the library directory. Note that audio plugins
266      * are not loaded here, they are managed by AudioDriver.
267      */
268     void loadAll();
269 
270     /**
271      * Unloads all plugins.
272      */
273     void unloadAll();
274 
275     /**
276      * Change the currently active plugin for the current thread to that attributed
277      * with the given @a id.
278      */
279     void setActivePluginId(pluginid_t id);
280 
281     /**
282      * Returns the unique identifier of the currently active plugin. The currently
283      * active plugin is tracked separately for each thread.
284      */
285     pluginid_t activePluginId() const;
286 
287     /**
288      * Locate the LibraryFile attributed with the given @a id.
289      */
290     de::LibraryFile const &fileForPlugin(pluginid_t id) const;
291 
292     /**
293      * Locate the address of the named, exported procedure in the plugin.
294      */
295     void *findEntryPoint(pluginid_t pluginId, char const *fn) const;
296 
297     bool exchangeGameEntryPoints(pluginid_t pluginId);
298 
299     /**
300      * Returns the current game plugin's entrypoints.
301      */
302     GameExports &gameExports() const;
303 
304 public:  // Function hooks: ----------------------------------------------------------
305 
306     /**
307      * Describes a function hook.
308      */
309     struct Hook
310     {
311         /**
312          * Returns @c true if the hook matches @a other.
313          * Note that if the plugin Id of either is not valid then this attribute is
314          * considered @em wild and therefore plugin Ids are ignored when matching.
315          */
316         bool        operator == (Hook const &other) const;
317         inline bool operator != (Hook const &other) const { return !(*this == other); }
318 
319         /**
320          * Execute the hook function and return the result.
321          *
322          * @param parm  Integer paramater to pass to the hook function.
323          * @param data  Pointer paramater to pass to the hook function.
324          *
325          * @return  Hook function return value.
326          */
327         int execute(int parm = 0, void *data = nullptr) const;
328 
329         /**
330          * Returns the unique Id attributed to the plugin that registered the hook,
331          * or @c 0 (not valid plugin Id) if a plugin is not attributed.
332          */
333         pluginid_t pluginId() const;
334 
335     private:
336         friend class Plugins;
337 
338         HookType _type       = NUM_HOOK_TYPES/*invalid type*/;
339         hookfunc_t _function = nullptr;
340         pluginid_t _pluginId = 0/*invalid ID*/;
341     };
342 
343     /**
344      * Returns @c true if one or more hooks of the given @a type is registered.
345      *
346      * @see forAllHooks(), callAllHooks()
347      */
348     bool hasHook(HookType type) const;
349 
350     /**
351      * Add a new @a function hook of the given @a type.
352      */
353     void addHook(HookType type, hookfunc_t function);
354 
355     /**
356      * Remove a @a function hook of the given @a type.
357      */
358     bool removeHook(HookType type, hookfunc_t function);
359 
360     /**
361      * Iterate through the registered Hooks.
362      *
363      * @param func  Callback to make for each Hook.
364      *
365      * @see callAllHooks()
366      */
367     de::LoopResult forAllHooks(HookType type, std::function<de::LoopResult (Hook const &)> func) const;
368 
369     /**
370      * Convenient method of executing all hook functions of the given @a type in
371      * registration order, passing the same paramater values to each.
372      *
373      * @param type  Hook-type identifier.
374      * @param parm  Integer data paramater to pass to the hook function.
375      * @param data  Pointer data paramater to pass to the hook function.
376      *
377      * @return  Bit zero is set if one or more hooks completed successfully (returned
378      * non-zero). Bit one is set if @em all the hooks completed successfully.
379      *
380      * @see forAllHooks()
381      */
382     int callAllHooks(HookType type, int parm = 0, void *data = nullptr);
383 
384 private:
385     DENG2_PRIVATE(d)
386 };
387 
388 #endif  // __cplusplus
389 
390 /**
391  * Registers a new hook function. A plugin can call this to add a hook function to be
392  * executed at the time specified by @a type.
393  *
394  * @param type      Hook-type identifier.
395  * @param function  Function pointer to hook.
396  *
397  * @return  @c true if successfully registered.
398  */
399 LIBDOOMSDAY_EXTERN_C LIBDOOMSDAY_PUBLIC
400 int Plug_AddHook(HookType type, hookfunc_t function);
401 
402 /**
403  * Removes a @a function hook from the register.
404  *
405  * @param type      Hook-type identifier.
406  * @param function  Function pointer to hook.
407  *
408  * @return  @c true if found and removed.
409  */
410 LIBDOOMSDAY_EXTERN_C LIBDOOMSDAY_PUBLIC
411 int Plug_RemoveHook(HookType type, hookfunc_t function);
412 
413 /**
414  * Check if there are any hooks of the given @a type registered.
415  *
416  * @param type  Hook-type identifier to lookup.
417  *
418  * @return  @c true if one or more hooks are registered for given @a type.
419  */
420 LIBDOOMSDAY_EXTERN_C LIBDOOMSDAY_PUBLIC
421 int Plug_CheckForHook(HookType type);
422 
423 /**
424  * Provides a way for plugins (e.g., games) to notify the engine of important events.
425  *
426  * @param notification  One of the DD_NOTIFY_* enums.
427  * @param param         Additional arguments about the notification, depending on the
428  *                      notification type.
429  */
430 LIBDOOMSDAY_EXTERN_C LIBDOOMSDAY_PUBLIC
431 void Plug_Notify(int notification, void *data);
432 
433 #endif  // LIBDOOMSDAY_PLUGINS_H
434