ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/plugins.C
Revision: 1.47
Committed: Mon Jun 4 12:19:09 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.46: +1 -43 lines
Log Message:
rename arch->name to arch->archname for preparation of subclassing object

File Contents

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Crossfire TRT is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51
20 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * The authors can be reached via e-mail to <crossfire@schmorp.de>
23 */
24
25 /*****************************************************************************/
26 /* This is the server-side plugin management part. */
27 /*****************************************************************************/
28 /* Original code by Yann Chachkoff (yann.chachkoff@mailandnews.com). */
29 /* Special thanks to: */
30 /* David Delbecq (david.delbecq@mailandnews.com); */
31 /* Joris Bontje (jbontje@suespammers.org); */
32 /* Philip Currlin (?); */
33 /*****************************************************************************/
34
35 /*****************************************************************************/
36 /* First, the headers. We only include plugin.h, because all other includes */
37 /* are done into it, and plugproto.h (which is used only by this file). */
38 /*****************************************************************************/
39
40 #include <plugin.h>
41
42 #ifndef __CEXTRACT__
43 # include <sproto.h>
44 #endif
45
46 #define NR_OF_HOOKS 74
47
48 static const hook_entry plug_hooks[NR_OF_HOOKS] = {
49 {cfapi_system_register_global_event, 1, "cfapi_system_register_global_event"},
50 {cfapi_system_unregister_global_event, 3, "cfapi_system_unregister_global_event"},
51 {cfapi_system_check_path, 4, "cfapi_system_check_path"},
52 {NULL, 5, "cfapi_system_re_cmp"},
53 {cfapi_system_strdup, 6, "cfapi_system_strdup"},
54 {cfapi_system_directory, 7, "cfapi_system_directory"},
55 {cfapi_system_find_animation, 8, "cfapi_system_find_animation"},
56 {cfapi_object_clean_object, 9, "cfapi_object_clean_object"},
57 {cfapi_object_on_same_map, 10, "cfapi_object_on_same_map"},
58 {cfapi_object_get_key, 11, "cfapi_object_get_key"},
59 {cfapi_object_set_key, 12, "cfapi_object_set_key"},
60 {cfapi_object_get_property, 13, "cfapi_object_get_property"},
61 {cfapi_object_set_property, 14, "cfapi_object_set_property"},
62 {cfapi_object_apply, 15, "cfapi_object_apply"},
63 {cfapi_object_identify, 16, "cfapi_object_identify"},
64 {cfapi_object_describe, 17, "cfapi_object_describe"},
65 {cfapi_object_drain, 18, "cfapi_object_drain"},
66 {cfapi_object_fix, 19, "cfapi_object_fix"},
67 {cfapi_object_give_skill, 20, "cfapi_object_give_skill"},
68 {cfapi_object_transmute, 21, "cfapi_object_transmute"},
69 {cfapi_object_remove, 22, "cfapi_object_remove"},
70 {cfapi_object_delete, 23, "cfapi_object_delete"},
71 {cfapi_object_clone, 24, "cfapi_object_clone"},
72 {cfapi_object_find, 25, "cfapi_object_find"},
73 {cfapi_object_create, 26, "cfapi_object_create"},
74 {cfapi_object_insert, 27, "cfapi_object_insert"},
75 {cfapi_object_split, 28, "cfapi_object_split"},
76 {cfapi_object_merge, 29, "cfapi_object_merge"},
77 {cfapi_object_distance, 30, "cfapi_object_distance"},
78 {cfapi_object_update, 31, "cfapi_object_update"},
79 {cfapi_object_clear, 32, "cfapi_object_clear"},
80 {cfapi_object_reset, 33, "cfapi_object_reset"},
81 {cfapi_object_check_inventory, 34, "cfapi_object_check_inventory"},
82 {cfapi_object_spring_trap, 35, "cfapi_object_spring_trap"},
83 {cfapi_object_check_trigger, 36, "cfapi_object_check_trigger"},
84 {cfapi_object_query_cost, 37, "cfapi_object_query_cost"},
85 {cfapi_object_query_money, 38, "cfapi_object_query_money"},
86 {cfapi_object_cast, 39, "cfapi_object_cast"},
87 {cfapi_object_learn_spell, 40, "cfapi_object_learn_spell"},
88 {cfapi_object_forget_spell, 41, "cfapi_object_forget_spell"},
89 {cfapi_object_check_spell, 42, "cfapi_object_check_spell"},
90 {cfapi_object_pay_amount, 43, "cfapi_object_pay_amount"},
91 {cfapi_object_pay_item, 44, "cfapi_object_pay_item"},
92 {cfapi_object_transfer, 45, "cfapi_object_transfer"},
93 {cfapi_object_drop, 46, "cfapi_object_drop"},
94 {cfapi_object_take, 47, "cfapi_object_take"},
95 {cfapi_object_find_archetype_inside, 48, "cfapi_object_find_archetype_inside"},
96 {cfapi_object_say, 49, "cfapi_object_say"},
97 {cfapi_map_get_map, 50, "cfapi_map_get_map"},
98 {cfapi_map_has_been_loaded, 51, "cfapi_map_has_been_loaded"},
99 {cfapi_map_create_path, 52, "cfapi_map_create_path"},
100 {cfapi_map_get_map_property, 53, "cfapi_map_get_property"},
101 {cfapi_map_set_map_property, 54, "cfapi_map_set_property"},
102 {cfapi_map_out_of_map, 55, "cfapi_map_out_of_map"},
103 {cfapi_map_update_position, 56, "cfapi_map_update_position"},
104 {cfapi_map_delete_map, 57, "cfapi_map_delete_map"},
105 {cfapi_map_message, 58, "cfapi_map_message"},
106 {cfapi_map_get_object_at, 59, "cfapi_map_get_object_at"},
107 {cfapi_map_get_flags, 60, "cfapi_map_get_flags"},
108 {cfapi_map_present_arch_by_name, 61, "cfapi_map_present_arch_by_name"},
109 {cfapi_player_find, 62, "cfapi_player_find"},
110 {cfapi_player_message, 63, "cfapi_player_message"},
111 {cfapi_player_send_inventory, 64, "cfapi_player_send_inventory"},
112 {cfapi_object_teleport, 65, "cfapi_object_teleport"},
113 {cfapi_object_speak, 66, "cfapi_object_speak"},
114 {cfapi_object_pickup, 67, "cfapi_object_pickup"},
115 {cfapi_object_move, 68, "cfapi_object_move"},
116 {cfapi_object_apply_below, 69, "cfapi_object_apply_below"},
117 {cfapi_archetype_get_first, 70, "cfapi_archetype_get_first"},
118 {cfapi_archetype_get_property, 71, "cfapi_archetype_get_property"},
119 {cfapi_party_get_property, 72, "cfapi_party_get_property"},
120 {cfapi_region_get_property, 73, "cfapi_region_get_property"},
121 };
122 int plugin_number = 0;
123 crossfire_plugin *plugins_list = NULL;
124
125 /*****************************************************************************/
126
127 /* NEW PLUGIN STUFF STARTS HERE */
128
129 /*****************************************************************************/
130
131 /**
132 * Notify clients about a removed object.
133 *
134 * @param op the object about to be removed from its environment; it must still
135 * be present in its environment
136 */
137 static void
138 send_removed_object (object *op)
139 {
140 object *tmp;
141
142 if (op->env == NULL)
143 {
144 /* no action necessary: remove_ob() notifies the client */
145 return;
146 }
147
148 tmp = op->in_player ();
149 if (!tmp)
150 {
151 for_all_players (pl)
152 if (pl->ob->container == op->env)
153 {
154 tmp = pl->ob;
155 break;
156 }
157 }
158
159 if (tmp)
160 esrv_del_item (tmp->contr, op->count);
161 }
162
163 extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr);
164 extern "C" void *cfperl_getPluginProperty (int *type, ...);
165 extern "C" int cfperl_postInitPlugin ();
166 extern "C" int cfperl_closePlugin ();
167
168 // this is a temporary hack till the old plugin stuff is removed
169 int
170 plugins_init_perl ()
171 {
172 f_plug_init initfunc;
173 f_plug_api propfunc;
174 f_plug_postinit postfunc;
175 f_plug_postinit closefunc;
176 int i;
177 crossfire_plugin *cp;
178 crossfire_plugin *ccp;
179
180 initfunc = (f_plug_init) cfperl_initPlugin;
181 propfunc = (f_plug_api) cfperl_getPluginProperty;
182 postfunc = (f_plug_postinit) cfperl_postInitPlugin;
183 closefunc = (f_plug_postinit) cfperl_closePlugin;
184 i = initfunc ("2.0", cfapi_get_hooks);
185 cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin));
186 for (i = 0; i < NR_EVENTS; i++)
187 cp->gevent[i] = NULL;
188 cp->eventfunc = 0;
189 cp->propfunc = propfunc;
190 cp->closefunc = closefunc;
191 cp->libptr = 0;
192 strcpy (cp->id, (const char *) propfunc (&i, "Identification"));
193 strcpy (cp->fullname, (const char *) propfunc (&i, "FullName"));
194 cp->next = NULL;
195 cp->prev = NULL;
196 if (plugins_list == NULL)
197 {
198 plugins_list = cp;
199 }
200 else
201 {
202 for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
203 ;
204 ccp->next = cp;
205 cp->prev = ccp;
206 }
207 postfunc ();
208 plugin_number++;
209 return 0;
210 }
211
212 int
213 plugins_init_plugin (const char *libfile)
214 {
215 return 0;
216
217 LIBPTRTYPE ptr;
218 f_plug_init initfunc;
219 f_plug_api propfunc;
220 f_plug_api eventfunc;
221 f_plug_postinit postfunc;
222 f_plug_postinit closefunc;
223 int i;
224 crossfire_plugin *cp;
225 crossfire_plugin *ccp;
226
227 /* Open the plugin lib and load the required functions */
228 ptr = plugins_dlopen (libfile);
229 if (ptr == NULL)
230 {
231 LOG (llevError, "Error trying to load %s: %s\n", libfile, plugins_dlerror ());
232 return -1;
233 }
234 initfunc = (f_plug_init) plugins_dlsym (ptr, "initPlugin");
235 if (initfunc == NULL)
236 {
237 LOG (llevError, "Plugin error while requesting %s.initPlugin: %s\n", libfile, plugins_dlerror ());
238 plugins_dlclose (ptr);
239 return -1;
240 }
241 propfunc = (f_plug_api) plugins_dlsym (ptr, "getPluginProperty");
242 if (propfunc == NULL)
243 {
244 LOG (llevError, "Plugin error while requesting %s.getPluginProperty: %s\n", libfile, plugins_dlerror ());
245 plugins_dlclose (ptr);
246 return -1;
247 }
248 eventfunc = (f_plug_api) plugins_dlsym (ptr, "eventListener");
249 if (eventfunc == NULL)
250 {
251 LOG (llevError, "Plugin error while requesting %s.eventListener: %s\n", libfile, plugins_dlerror ());
252 plugins_dlclose (ptr);
253 return -1;
254 }
255 postfunc = (f_plug_postinit) plugins_dlsym (ptr, "postInitPlugin");
256 if (postfunc == NULL)
257 {
258 LOG (llevError, "Plugin error while requesting %s.postInitPlugin: %s\n", libfile, plugins_dlerror ());
259 plugins_dlclose (ptr);
260 return -1;
261 }
262 closefunc = (f_plug_postinit) plugins_dlsym (ptr, "closePlugin");
263 if (postfunc == NULL)
264 {
265 LOG (llevError, "Plugin error while requesting %s.closePlugin: %s\n", libfile, plugins_dlerror ());
266 plugins_dlclose (ptr);
267 return -1;
268 }
269 i = initfunc ("2.0", cfapi_get_hooks);
270 cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin));
271 for (i = 0; i < NR_EVENTS; i++)
272 cp->gevent[i] = NULL;
273 cp->eventfunc = eventfunc;
274 cp->propfunc = propfunc;
275 cp->closefunc = closefunc;
276 cp->libptr = ptr;
277 strcpy (cp->id, (const char *) propfunc (&i, "Identification"));
278 strcpy (cp->fullname, (const char *) propfunc (&i, "FullName"));
279 cp->next = NULL;
280 cp->prev = NULL;
281 if (plugins_list == NULL)
282 {
283 plugins_list = cp;
284 }
285 else
286 {
287 for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
288 ;
289 ccp->next = cp;
290 cp->prev = ccp;
291 }
292 postfunc ();
293 plugin_number++;
294 return 0;
295 }
296
297 void *
298 cfapi_get_hooks (int *type, ...)
299 {
300 va_list args;
301 int request_type;
302 char *buf;
303 int fid;
304 f_plug_api rv;
305 int i;
306
307 va_start (args, type);
308 request_type = va_arg (args, int);
309
310 if (request_type == 0)
311 { /* By nr */
312 fid = va_arg (args, int);
313
314 if (fid < 0 || fid >= NR_OF_HOOKS)
315 {
316 rv = NULL;
317 *type = CFAPI_NONE;
318 }
319 else
320 {
321 rv = plug_hooks[fid].func;
322 *type = CFAPI_FUNC;
323 }
324 }
325 else
326 { /* by name */
327 buf = va_arg (args, char *);
328
329 rv = NULL;
330 for (i = 0; i < NR_OF_HOOKS; i++)
331 {
332 if (!strcmp (buf, plug_hooks[i].fname))
333 {
334 rv = plug_hooks[i].func;
335 *type = CFAPI_FUNC;
336 break;
337 }
338 }
339 if (rv == NULL)
340 {
341 *type = CFAPI_NONE;
342 }
343 }
344 va_end (args);
345 return (void *) rv;
346 }
347
348 int
349 plugins_remove_plugin (const char *id)
350 {
351 crossfire_plugin *cp;
352
353 if (plugins_list == NULL)
354 return -1;
355
356 for (cp = plugins_list; cp != NULL; cp = cp->next)
357 {
358 if (!strcmp (id, cp->id) && cp->libptr)
359 {
360 crossfire_plugin *n;
361 crossfire_plugin *p;
362
363 n = cp->next;
364 p = cp->prev;
365 plugins_dlclose (cp->libptr);
366 if (n != NULL)
367 {
368 if (p != NULL)
369 {
370 n->prev = p;
371 p->next = n;
372 }
373 else
374 {
375 n->prev = NULL;
376 plugins_list = n;
377 }
378 }
379 else
380 {
381 if (p != NULL)
382 p->next = NULL;
383 else
384 plugins_list = NULL;
385 }
386 free (cp);
387 plugin_number--;
388 return 0;
389 }
390 }
391 return -1;
392 }
393
394 crossfire_plugin *
395 plugins_find_plugin (const char *id)
396 {
397 crossfire_plugin *cp;
398
399 if (plugins_list == NULL)
400 return NULL;
401
402 for (cp = plugins_list; cp != NULL; cp = cp->next)
403 {
404 if (!strcmp (id, cp->id))
405 {
406 return cp;
407 }
408 }
409 return NULL;
410 }
411
412 /*****************************************************************************/
413
414 /* Displays a list of loaded plugins (keystrings and description) in the */
415
416 /* game log window. */
417
418 /*****************************************************************************/
419 void
420 plugins_display_list (object *op)
421 {
422 crossfire_plugin *cp;
423
424 new_draw_info (NDI_UNIQUE, 0, op, "List of loaded plugins:");
425 new_draw_info (NDI_UNIQUE, 0, op, "-----------------------");
426
427 if (plugins_list == NULL)
428 return;
429
430 for (cp = plugins_list; cp != NULL; cp = cp->next)
431 {
432 new_draw_info_format (NDI_UNIQUE, 0, op, "%s, %s", cp->id, cp->fullname);
433 }
434 }
435
436 /* SYSTEM-RELATED HOOKS */
437
438 void *
439 cfapi_system_find_animation (int *type, ...)
440 {
441 va_list args;
442 static int rv;
443 char *anim;
444
445 va_start (args, type);
446 anim = va_arg (args, char *);
447
448 va_end (args);
449
450 rv = find_animation (anim);
451 *type = CFAPI_INT;
452 return &rv;
453 }
454
455 void *
456 cfapi_system_strdup (int *type, ...)
457 {
458 va_list args;
459 char *txt;
460
461 va_start (args, type);
462 txt = va_arg (args, char *);
463
464 va_end (args);
465 *type = CFAPI_STRING;
466 return strdup (txt);
467 }
468
469 void *
470 cfapi_system_register_global_event (int *type, ...)
471 {
472 va_list args;
473 int eventcode;
474 char *pname;
475 f_plug_api hook;
476 crossfire_plugin *cp;
477
478 va_start (args, type);
479 eventcode = va_arg (args, int);
480 pname = va_arg (args, char *);
481
482 hook = va_arg (args, f_plug_api);
483
484 va_end (args);
485 cp = plugins_find_plugin (pname);
486 cp->gevent[eventcode] = hook;
487 return NULL;
488 }
489
490 void *
491 cfapi_system_unregister_global_event (int *type, ...)
492 {
493 va_list args;
494 int eventcode;
495 char *pname;
496 crossfire_plugin *cp;
497
498 va_start (args, type);
499 eventcode = va_arg (args, int);
500 pname = va_arg (args, char *);
501
502 cp = plugins_find_plugin (pname);
503 cp->gevent[eventcode] = NULL;
504
505 va_end (args);
506 return NULL;
507 }
508
509 void *
510 cfapi_system_check_path (int *type, ...)
511 {
512 va_list args;
513 static int rv;
514 char *name;
515 int prepend_dir;
516
517 va_start (args, type);
518
519 name = va_arg (args, char *);
520 prepend_dir = va_arg (args, int);
521
522 rv = check_path (name, prepend_dir);
523
524 va_end (args);
525 *type = CFAPI_INT;
526 return &rv;
527 }
528
529 void *
530 cfapi_system_directory (int *type, ...)
531 {
532 va_list args;
533 int dirtype;
534
535 va_start (args, type);
536
537 dirtype = va_arg (args, int);
538
539 va_end (args);
540
541 *type = CFAPI_STRING;
542
543 switch (dirtype)
544 {
545 case 0:
546 return (char *)settings.mapdir;
547 break;
548
549 case 1:
550 return (char *)settings.uniquedir;
551 break;
552
553 case 2:
554 return (char *)settings.tmpdir;
555 break;
556
557 case 3:
558 return (char *)settings.confdir;
559 break;
560
561 case 4:
562 return (char *)settings.localdir;
563 break;
564
565 case 5:
566 return (char *)settings.playerdir;
567 break;
568
569 case 6:
570 return (char *)settings.datadir;
571 break;
572 }
573
574 *type = CFAPI_NONE;
575 return NULL;
576 }
577
578
579 /* MAP RELATED HOOKS */
580
581 void *
582 cfapi_map_get_map (int *type, ...)
583 {
584 abort ();
585 }
586
587 void *
588 cfapi_map_has_been_loaded (int *type, ...)
589 {
590 abort ();
591 }
592
593 void *
594 cfapi_map_create_path (int *type, ...)
595 {
596 abort ();
597 }
598
599 void *
600 cfapi_map_get_map_property (int *type, ...)
601 {
602 abort ();
603 }
604
605 void *
606 cfapi_map_set_map_property (int *type, ...)
607 {
608 abort ();
609 }
610
611 void *
612 cfapi_map_out_of_map (int *type, ...)
613 {
614 abort ();
615 }
616
617 void *
618 cfapi_map_update_position (int *type, ...)
619 {
620 va_list args;
621 maptile *map;
622 int x, y;
623
624 va_start (args, type);
625
626 map = va_arg (args, maptile *);
627 x = va_arg (args, int);
628 y = va_arg (args, int);
629
630 map->at (x, y).flags_ &= ~P_UPTODATE;
631
632 va_end (args);
633 *type = CFAPI_NONE;
634 return NULL;
635 }
636
637 void *
638 cfapi_map_delete_map (int *type, ...)
639 {
640 abort ();
641 }
642
643 void *
644 cfapi_map_message (int *type, ...)
645 {
646 va_list args;
647 maptile *map;
648 char *string;
649 int color;
650
651 va_start (args, type);
652 map = va_arg (args, maptile *);
653 string = va_arg (args, char *);
654 color = va_arg (args, int);
655
656 va_end (args);
657
658 new_info_map (color, map, string);
659 *type = CFAPI_NONE;
660 return NULL;
661 }
662
663 void *
664 cfapi_map_get_object_at (int *type, ...)
665 {
666 va_list args;
667 maptile *map;
668 int x, y;
669 object *rv;
670
671 va_start (args, type);
672 map = va_arg (args, maptile *);
673 x = va_arg (args, int);
674 y = va_arg (args, int);
675
676 va_end (args);
677
678 rv = GET_MAP_OB (map, x, y);
679 *type = CFAPI_POBJECT;
680 return rv;
681 }
682
683 void *
684 cfapi_map_get_flags (int *type, ...)
685 {
686 va_list args;
687 sint16 x, y;
688 sint16 *nx, *ny;
689 static maptile *map;
690 maptile **newmap;
691 static int rv;
692
693 va_start (args, type);
694
695 map = va_arg (args, maptile *);
696 newmap = va_arg (args, maptile **);
697 x = va_arg (args, int);
698 y = va_arg (args, int);
699
700 nx = va_arg (args, sint16 *);
701 ny = va_arg (args, sint16 *);
702 va_end (args);
703
704 rv = get_map_flags (map, newmap, x, y, nx, ny);
705
706 *type = CFAPI_INT;
707 return &rv;
708 }
709
710 void *
711 cfapi_map_present_arch_by_name (int *type, ...)
712 {
713 va_list args;
714 object *rv;
715 int x, y;
716 maptile *map;
717 char *msg;
718
719 va_start (args, type);
720
721 msg = va_arg (args, char *);
722 map = va_arg (args, maptile *);
723 x = va_arg (args, int);
724 y = va_arg (args, int);
725
726 va_end (args);
727
728 rv = present_arch (archetype::find (msg), map, x, y);
729 *type = CFAPI_POBJECT;
730 return rv;
731 }
732
733 /* OBJECT-RELATED HOOKS */
734
735 void *
736 cfapi_object_move (int *type, ...)
737 {
738 va_list args;
739 int kind;
740 object *op;
741 object *activator;
742 player *pl;
743 int direction;
744 static int rv = 0;
745
746 va_start (args, type);
747 kind = va_arg (args, int);
748
749 switch (kind)
750 {
751 case 0:
752 op = va_arg (args, object *);
753 direction = va_arg (args, int);
754 activator = va_arg (args, object *);
755
756 va_end (args);
757 rv = move_ob (op, direction, activator);
758 break;
759
760 case 1:
761 pl = va_arg (args, player *);
762 direction = va_arg (args, int);
763
764 va_end (args);
765 rv = move_player (pl->ob, direction);
766 break;
767 }
768 *type = CFAPI_INT;
769 return &rv;
770 }
771
772 void *
773 cfapi_object_get_key (int *type, ...)
774 {
775 va_list args;
776 char *rv;
777 char *keyname;
778 object *op;
779
780 va_start (args, type);
781 op = va_arg (args, object *);
782 keyname = va_arg (args, char *);
783
784 va_end (args);
785
786 rv = (char *) get_ob_key_value (op, keyname);
787 *type = CFAPI_STRING;
788 return rv;
789 }
790
791 void *
792 cfapi_object_set_key (int *type, ...)
793 {
794 va_list args;
795 char *keyname;
796 char *value;
797 object *op;
798
799 va_start (args, type);
800 op = va_arg (args, object *);
801 keyname = va_arg (args, char *);
802 value = va_arg (args, char *);
803
804 va_end (args);
805
806 set_ob_key_value (op, keyname, value, 0);
807 *type = CFAPI_NONE;
808 return NULL;
809 }
810
811 void *
812 cfapi_object_get_property (int *type, ...)
813 {
814 abort ();
815 }
816
817 void *
818 cfapi_object_set_property (int *type, ...)
819 {
820 abort ();
821 }
822
823 void *
824 cfapi_object_apply_below (int *type, ...)
825 {
826 va_list args;
827 object *applier;
828
829 va_start (args, type);
830
831 applier = va_arg (args, object *);
832
833 va_end (args);
834
835 player_apply_below (applier);
836 *type = CFAPI_NONE;
837 return NULL;
838 }
839
840 void *
841 cfapi_object_apply (int *type, ...)
842 {
843 va_list args;
844 object *applied;
845 object *applier;
846 int aflags;
847 static int rv;
848
849 va_start (args, type);
850
851 applied = va_arg (args, object *);
852 applier = va_arg (args, object *);
853 aflags = va_arg (args, int);
854
855 va_end (args);
856
857 *type = CFAPI_INT;
858 rv = manual_apply (applier, applied, aflags);
859 return &rv;
860 }
861
862 void *
863 cfapi_object_identify (int *type, ...)
864 {
865 va_list args;
866 object *op;
867
868 va_start (args, type);
869
870 op = va_arg (args, object *);
871
872 va_end (args);
873
874 identify (op);
875 *type = CFAPI_NONE;
876 return NULL;
877 }
878
879 void *
880 cfapi_object_describe (int *type, ...)
881 {
882 va_list args;
883 object *op;
884 object *owner;
885
886 va_start (args, type);
887
888 op = va_arg (args, object *);
889 owner = va_arg (args, object *);
890
891 va_end (args);
892
893 *type = CFAPI_STRING;
894 return (char *)describe_item (op, owner);
895 }
896
897 void *
898 cfapi_object_drain (int *type, ...)
899 {
900 abort ();
901 }
902
903 void *
904 cfapi_object_fix (int *type, ...)
905 {
906 va_list args;
907 object *op;
908
909 va_start (args, type);
910
911 op = va_arg (args, object *);
912
913 va_end (args);
914
915 op->update_stats ();
916
917 *type = CFAPI_NONE;
918 return NULL;
919 }
920
921 void *
922 cfapi_object_give_skill (int *type, ...)
923 {
924 va_list args;
925
926 object *op;
927 char *skillname;
928
929 va_start (args, type);
930
931 op = va_arg (args, object *);
932 skillname = va_arg (args, char *);
933
934 va_end (args);
935
936 *type = CFAPI_POBJECT;
937 return give_skill_by_name (op, skillname);
938 }
939
940 void *
941 cfapi_object_transmute (int *type, ...)
942 {
943 va_list args;
944
945 object *op;
946 object *chg;
947
948 va_start (args, type);
949
950 op = va_arg (args, object *);
951 chg = va_arg (args, object *);
952
953 va_end (args);
954
955 transmute_materialname (op, chg);
956 *type = CFAPI_NONE;
957 return NULL;
958 }
959
960 void *
961 cfapi_object_remove (int *type, ...)
962 {
963 va_list args;
964 object *op;
965
966 va_start (args, type);
967
968 op = va_arg (args, object *);
969
970 va_end (args);
971
972 send_removed_object (op);
973 op->remove ();
974 *type = CFAPI_NONE;
975 return NULL;
976 }
977
978 void *
979 cfapi_object_delete (int *type, ...)
980 {
981 va_list args;
982 object *op;
983
984 va_start (args, type);
985
986 op = va_arg (args, object *);
987
988 va_end (args);
989
990 op->destroy ();
991
992 *type = CFAPI_NONE;
993 return NULL;
994 }
995
996 void *
997 cfapi_object_clone (int *type, ...)
998 {
999 va_list args;
1000 object *op;
1001 int kind;
1002
1003 va_start (args, type);
1004
1005 op = va_arg (args, object *);
1006 kind = va_arg (args, int);
1007
1008 va_end (args);
1009
1010 if (kind == 0)
1011 {
1012 *type = CFAPI_POBJECT;
1013 return object_create_clone (op);
1014 }
1015 else
1016 {
1017 object *tmp = op->clone ();
1018 *type = CFAPI_POBJECT;
1019 return tmp;
1020 }
1021 }
1022 void *
1023 cfapi_object_find (int *type, ...)
1024 {
1025 va_list args;
1026 int ftype;
1027 void *rv;
1028 int ival;
1029 int ival2;
1030 char *sval;
1031 object *op;
1032
1033 va_start (args, type);
1034
1035 *type = CFAPI_POBJECT;
1036 ftype = va_arg (args, int);
1037
1038 switch (ftype)
1039 {
1040 case 0:
1041 ival = va_arg (args, int);
1042
1043 rv = find_object (ival);
1044 break;
1045
1046 case 1:
1047 sval = va_arg (args, char *);
1048
1049 rv = find_object_name (sval);
1050 break;
1051
1052 case 2:
1053 op = va_arg (args, object *);
1054 ival = va_arg (args, int);
1055 ival2 = va_arg (args, int);
1056
1057 rv = find_obj_by_type_subtype (op, ival, ival2);
1058 break;
1059
1060 case 3:
1061 op = va_arg (args, object *);
1062
1063 rv = op->in_player ();
1064 break;
1065
1066 default:
1067 rv = NULL;
1068 *type = CFAPI_NONE;
1069 break;
1070 }
1071
1072 va_end (args);
1073
1074 return rv;
1075 }
1076
1077 void *
1078 cfapi_object_create (int *type, ...)
1079 {
1080 va_list args;
1081 int ival;
1082
1083 va_start (args, type);
1084 ival = va_arg (args, int);
1085
1086 *type = CFAPI_POBJECT;
1087 switch (ival)
1088 {
1089 case 0:
1090 va_end (args);
1091 return object::create ();
1092 break;
1093
1094 case 1: /* Named object. Nearly the old plugin behavior, but we don't add artifact suffixes */
1095 {
1096 char *sval;
1097 object *op;
1098 sval = va_arg (args, char *);
1099
1100 op = get_archetype_by_object_name (sval);
1101
1102 if (strcmp (query_name (op), ARCH_SINGULARITY) == 0)
1103 {
1104 op->destroy ();
1105 /* Try with archetype names... */
1106 op = get_archetype (sval);
1107 if (strcmp (query_name (op), ARCH_SINGULARITY) == 0)
1108 {
1109 op->destroy ();
1110 *type = CFAPI_NONE;
1111 va_end (args);
1112 return NULL;
1113 }
1114 }
1115 va_end (args);
1116 return op;
1117 }
1118 break;
1119
1120 default:
1121 *type = CFAPI_NONE;
1122 va_end (args);
1123 return NULL;
1124 break;
1125 }
1126 }
1127 void *
1128 cfapi_object_insert (int *type, ...)
1129 {
1130 va_list args;
1131 object *op;
1132 object *orig;
1133 maptile *map;
1134 int flag, x, y;
1135 int itype;
1136 char *arch_string;
1137 void *rv = NULL;
1138
1139 va_start (args, type);
1140
1141 op = va_arg (args, object *);
1142 itype = va_arg (args, int);
1143
1144 switch (itype)
1145 {
1146 case 0:
1147 map = va_arg (args, maptile *);
1148 orig = va_arg (args, object *);
1149 flag = va_arg (args, int);
1150 x = va_arg (args, int);
1151 y = va_arg (args, int);
1152
1153 rv = insert_ob_in_map_at (op, map, orig, flag, x, y);
1154 *type = CFAPI_POBJECT;
1155 break;
1156
1157 case 1:
1158 map = va_arg (args, maptile *);
1159 orig = va_arg (args, object *);
1160 flag = va_arg (args, int);
1161
1162 rv = insert_ob_in_map (op, map, orig, flag);
1163 *type = CFAPI_POBJECT;
1164 break;
1165
1166 case 2:
1167 arch_string = va_arg (args, char *);
1168
1169 replace_insert_ob_in_map (arch_string, op);
1170 *type = CFAPI_NONE;
1171 break;
1172
1173 case 3:
1174 orig = va_arg (args, object *);
1175
1176 rv = insert_ob_in_ob (op, orig);
1177 if (orig->type == PLAYER)
1178 {
1179 esrv_send_item (orig, op);
1180 }
1181 *type = CFAPI_POBJECT;
1182 break;
1183 }
1184
1185 va_end (args);
1186
1187 return rv;
1188 }
1189
1190 void *
1191 cfapi_object_split (int *type, ...)
1192 {
1193 va_list args;
1194
1195 int nr;
1196 object *op;
1197
1198 va_start (args, type);
1199
1200 op = va_arg (args, object *);
1201 nr = va_arg (args, int);
1202
1203 va_end (args);
1204 *type = CFAPI_POBJECT;
1205 return get_split_ob (op, nr);
1206 }
1207
1208 void *
1209 cfapi_object_merge (int *type, ...)
1210 {
1211 va_list args;
1212 object *op;
1213 object *op2;
1214
1215 va_start (args, type);
1216
1217 op = va_arg (args, object *);
1218 op2 = va_arg (args, object *);
1219
1220 va_end (args);
1221
1222
1223 *type = CFAPI_POBJECT;
1224 return merge_ob (op, op2);
1225 }
1226
1227 void *
1228 cfapi_object_distance (int *type, ...)
1229 {
1230 va_list args;
1231 static int rv;
1232 object *op;
1233 object *op2;
1234
1235 va_start (args, type);
1236
1237 op = va_arg (args, object *);
1238 op2 = va_arg (args, object *);
1239
1240 va_end (args);
1241
1242 *type = CFAPI_INT;
1243 rv = distance (op, op2);
1244 return &rv;
1245 }
1246
1247 void *
1248 cfapi_object_update (int *type, ...)
1249 {
1250 va_list args;
1251 int action;
1252 object *op;
1253
1254 va_start (args, type);
1255
1256 op = va_arg (args, object *);
1257 action = va_arg (args, int);
1258
1259 va_end (args);
1260
1261 update_object (op, action);
1262 *type = CFAPI_NONE;
1263 return NULL;
1264 }
1265
1266 void *
1267 cfapi_object_clear (int *type, ...)
1268 {
1269 abort ();
1270 }
1271
1272 void *
1273 cfapi_object_reset (int *type, ...)
1274 {
1275 abort ();
1276 }
1277
1278 void *
1279 cfapi_object_check_inventory (int *type, ...)
1280 {
1281 va_list args;
1282 object *op;
1283 object *op2;
1284 int checktype;
1285 object *ret = NULL;
1286
1287 va_start (args, type);
1288
1289 op = va_arg (args, object *);
1290 op2 = va_arg (args, object *);
1291 checktype = va_arg (args, int);
1292
1293 if (checktype == 0)
1294 {
1295 check_inv (op, op2);
1296 *type = CFAPI_NONE;
1297 }
1298 else
1299 {
1300 ret = check_inv_recursive (op, op2);
1301 *type = CFAPI_POBJECT;
1302 }
1303
1304 va_end (args);
1305
1306 return ret;
1307 }
1308
1309 void *
1310 cfapi_object_clean_object (int *type, ...)
1311 {
1312 abort ();
1313 }
1314
1315 void *
1316 cfapi_object_on_same_map (int *type, ...)
1317 {
1318 va_list args;
1319 static int rv;
1320 object *op1;
1321 object *op2;
1322
1323 va_start (args, type);
1324 op1 = va_arg (args, object *);
1325 op2 = va_arg (args, object *);
1326
1327 rv = on_same_map (op1, op2);
1328 va_end (args);
1329
1330 *type = CFAPI_INT;
1331 return &rv;
1332 }
1333
1334 void *
1335 cfapi_object_spring_trap (int *type, ...)
1336 {
1337 object *trap;
1338 object *victim;
1339 va_list args;
1340
1341 va_start (args, type);
1342 trap = va_arg (args, object *);
1343 victim = va_arg (args, object *);
1344
1345 va_end (args);
1346
1347 spring_trap (trap, victim);
1348 *type = CFAPI_NONE;
1349 return NULL;
1350 }
1351
1352 void *
1353 cfapi_object_check_trigger (int *type, ...)
1354 {
1355 object *op;
1356 object *cause;
1357 va_list args;
1358 static int rv;
1359
1360 va_start (args, type);
1361 op = va_arg (args, object *);
1362 cause = va_arg (args, object *);
1363
1364 va_end (args);
1365
1366 rv = check_trigger (op, cause);
1367 *type = CFAPI_INT;
1368 return &rv;
1369 }
1370
1371 void *
1372 cfapi_object_query_cost (int *type, ...)
1373 {
1374 object *op;
1375 object *who;
1376 int flags;
1377 va_list args;
1378 static int rv;
1379
1380 va_start (args, type);
1381 op = va_arg (args, object *);
1382 who = va_arg (args, object *);
1383 flags = va_arg (args, int);
1384
1385 va_end (args);
1386
1387 rv = query_cost (op, who, flags);
1388 *type = CFAPI_INT;
1389 return &rv;
1390 }
1391
1392 void *
1393 cfapi_object_query_money (int *type, ...)
1394 {
1395 object *op;
1396 va_list args;
1397 static int rv;
1398
1399 va_start (args, type);
1400 op = va_arg (args, object *);
1401
1402 va_end (args);
1403
1404 rv = query_money (op);
1405 *type = CFAPI_INT;
1406 return &rv;
1407 }
1408
1409 void *
1410 cfapi_object_cast (int *type, ...)
1411 {
1412 object *op;
1413 object *sp;
1414 int dir;
1415 char *str;
1416 object *caster;
1417 va_list args;
1418 static int rv;
1419
1420 va_start (args, type);
1421 op = va_arg (args, object *);
1422 caster = va_arg (args, object *);
1423 dir = va_arg (args, int);
1424 sp = va_arg (args, object *);
1425 str = va_arg (args, char *);
1426
1427 va_end (args);
1428 rv = cast_spell (op, caster, dir, sp, str);
1429 *type = CFAPI_INT;
1430 return &rv;
1431 }
1432
1433 void *
1434 cfapi_object_learn_spell (int *type, ...)
1435 {
1436 object *op;
1437 object *sp;
1438 int prayer;
1439 va_list args;
1440
1441 va_start (args, type);
1442 op = va_arg (args, object *);
1443 sp = va_arg (args, object *);
1444 prayer = va_arg (args, int);
1445
1446 va_end (args);
1447 do_learn_spell (op, sp, prayer);
1448 *type = CFAPI_NONE;
1449 return NULL;
1450 }
1451
1452 void *
1453 cfapi_object_forget_spell (int *type, ...)
1454 {
1455 object *op;
1456 object *sp;
1457 va_list args;
1458
1459 va_start (args, type);
1460 op = va_arg (args, object *);
1461 sp = va_arg (args, object *);
1462
1463 va_end (args);
1464 do_forget_spell (op, query_name (sp));
1465 *type = CFAPI_NONE;
1466 return NULL;
1467 }
1468
1469 void *
1470 cfapi_object_check_spell (int *type, ...)
1471 {
1472 object *op;
1473 char *spellname;
1474 va_list args;
1475 object *rv;
1476
1477 va_start (args, type);
1478 op = va_arg (args, object *);
1479 spellname = va_arg (args, char *);
1480
1481 va_end (args);
1482 rv = check_spell_known (op, spellname);
1483 *type = CFAPI_POBJECT;
1484 return rv;
1485 }
1486
1487 void *
1488 cfapi_object_pay_amount (int *type, ...)
1489 {
1490 object *op;
1491 uint64 amount;
1492 va_list args;
1493 static int rv;
1494
1495 va_start (args, type);
1496 op = va_arg (args, object *);
1497
1498 amount = va_arg (args, uint64);
1499 va_end (args);
1500
1501 rv = pay_for_amount (amount, op);
1502 *type = CFAPI_INT;
1503 return &rv;
1504 }
1505
1506 void *
1507 cfapi_object_pay_item (int *type, ...)
1508 {
1509 object *op;
1510 object *tobuy;
1511
1512 va_list args;
1513 static int rv;
1514
1515 va_start (args, type);
1516 tobuy = va_arg (args, object *);
1517 op = va_arg (args, object *);
1518
1519 va_end (args);
1520
1521 rv = pay_for_item (tobuy, op);
1522 *type = CFAPI_INT;
1523 return &rv;
1524 }
1525
1526 void *
1527 cfapi_object_transfer (int *type, ...)
1528 {
1529 object *op;
1530 object *originator;
1531 int x, y, randompos, ttype;
1532 va_list args;
1533 static int rv = 0;
1534 maptile *map;
1535
1536 va_start (args, type);
1537 op = va_arg (args, object *);
1538 ttype = va_arg (args, int);
1539
1540 switch (ttype)
1541 {
1542 case 0:
1543 x = va_arg (args, int);
1544 y = va_arg (args, int);
1545 randompos = va_arg (args, int);
1546 originator = va_arg (args, object *);
1547
1548 va_end (args);
1549
1550 rv = transfer_ob (op, x, y, randompos, originator);
1551 *type = CFAPI_INT;
1552 return &rv;
1553 break;
1554
1555 case 1:
1556 x = va_arg (args, int);
1557 y = va_arg (args, int);
1558 map = va_arg (args, maptile *);
1559
1560 va_end (args);
1561 if (x < 0 || y < 0)
1562 {
1563 x = map->enter_x;
1564 y = map->enter_y;
1565 }
1566
1567 /*
1568 originator = object::create();
1569 EXIT_PATH(originator) = map->path;
1570 EXIT_X(originator) = x;
1571 EXIT_Y(originator) = y;
1572 printf("B Transfer: X=%d, Y=%d, OP=%s\n", x, y, op->name);*/
1573 /*enter_exit(op, originator); */
1574 insert_ob_in_map_at (op, map, NULL, 0, x, y);
1575 /*printf("A Transfer: X=%d, Y=%d, MAP=%s\n", x, y, op->map->name);
1576 originator->destroy ();
1577 */
1578 *type = CFAPI_INT;
1579 return &rv;
1580 break;
1581
1582 default:
1583 *type = CFAPI_NONE;
1584 return NULL;
1585 break;
1586 }
1587 }
1588
1589 void *
1590 cfapi_object_find_archetype_inside (int *type, ...)
1591 {
1592 object *op;
1593 int critera;
1594 char *str;
1595 va_list args;
1596 object *rv;
1597
1598 *type = CFAPI_POBJECT;
1599 va_start (args, type);
1600 op = va_arg (args, object *);
1601 critera = va_arg (args, int);
1602
1603 switch (critera)
1604 {
1605 case 0: /* By name, either exact or from query_name */
1606 str = va_arg (args, char *);
1607
1608 rv = present_arch_in_ob (archetype::find (str), op);
1609 if (rv == NULL)
1610 {
1611 object *tmp;
1612
1613 /* Search by query_name instead */
1614 for (tmp = op->inv; tmp; tmp = tmp->below)
1615 {
1616 if (!strncmp (query_name (tmp), str, strlen (str)))
1617 rv = tmp;
1618 if (!strncmp (tmp->name, str, strlen (str)))
1619 rv = tmp;
1620 if (rv != NULL)
1621 break;
1622 }
1623 }
1624 break;
1625
1626 default:
1627 rv = NULL;
1628 break;
1629 }
1630 va_end (args);
1631
1632 if (rv == NULL)
1633 {
1634 *type = CFAPI_NONE;
1635 }
1636 return rv;
1637 }
1638
1639 void *
1640 cfapi_object_drop (int *type, ...)
1641 {
1642 object *op;
1643 object *author;
1644 va_list args;
1645
1646 va_start (args, type);
1647 op = va_arg (args, object *);
1648 author = va_arg (args, object *);
1649
1650 va_end (args);
1651
1652 if (QUERY_FLAG (op, FLAG_NO_DROP))
1653 return NULL;
1654 drop (author, op);
1655
1656 if (author->type == PLAYER)
1657 {
1658 author->contr->count = 0;
1659 author->contr->ns->floorbox_update ();
1660 }
1661
1662 *type = CFAPI_NONE;
1663 return NULL;
1664 }
1665
1666 void *
1667 cfapi_object_take (int *type, ...)
1668 {
1669 object *op;
1670 object *author;
1671 va_list args;
1672
1673 va_start (args, type);
1674 op = va_arg (args, object *);
1675 author = va_arg (args, object *);
1676
1677 va_end (args);
1678 pick_up (author, op);
1679
1680 *type = CFAPI_NONE;
1681 return NULL;
1682 }
1683
1684 void *
1685 cfapi_object_say (int *type, ...)
1686 {
1687 abort ();
1688 }
1689
1690 void *
1691 cfapi_object_speak (int *type, ...)
1692 {
1693 abort ();
1694 }
1695
1696 /* PLAYER SUBCLASS */
1697 void *
1698 cfapi_player_find (int *type, ...)
1699 {
1700 abort ();
1701 }
1702
1703 void *
1704 cfapi_player_message (int *type, ...)
1705 {
1706 va_list args;
1707 int flags;
1708 int pri;
1709 object *pl;
1710 char *buf;
1711
1712 va_start (args, type);
1713
1714 flags = va_arg (args, int);
1715 pri = va_arg (args, int);
1716 pl = va_arg (args, object *);
1717 buf = va_arg (args, char *);
1718
1719 va_end (args);
1720
1721 new_draw_info (flags, pri, pl, buf);
1722 *type = CFAPI_NONE;
1723 return NULL;
1724 }
1725
1726 void *
1727 cfapi_player_send_inventory (int *type, ...)
1728 {
1729 /* Currently a stub. Do we really need this anymore ? */
1730 *type = CFAPI_NONE;
1731 return NULL;
1732 }
1733
1734 void *
1735 cfapi_object_teleport (int *type, ...)
1736 {
1737 maptile *map;
1738 int x, y;
1739 object *who;
1740 static int result;
1741 va_list args;
1742
1743 va_start (args, type);
1744 who = va_arg (args, object *);
1745 map = va_arg (args, maptile *);
1746 x = va_arg (args, int);
1747 y = va_arg (args, int);
1748
1749 if (!out_of_map (map, x, y))
1750 {
1751 int k;
1752 object *tmp;
1753
1754 k = find_first_free_spot (who, map, x, y);
1755 if (k == -1)
1756 {
1757 result = 1;
1758 return &result;
1759 }
1760
1761 send_removed_object (who);
1762 who->remove ();
1763
1764 for (tmp = who; tmp != NULL; tmp = tmp->more)
1765 tmp->x = x + freearr_x[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x),
1766 tmp->y = y + freearr_y[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y);
1767
1768 insert_ob_in_map (who, map, NULL, 0);
1769 result = 0;
1770 }
1771
1772 return &result;
1773 }
1774
1775 void *
1776 cfapi_object_pickup (int *type, ...)
1777 {
1778 object *who;
1779 object *what;
1780 va_list args;
1781
1782 va_start (args, type);
1783 who = va_arg (args, object *);
1784 what = va_arg (args, object *);
1785
1786 va_end (args);
1787
1788 pick_up (who, what);
1789 *type = CFAPI_NONE;
1790 return NULL;
1791 }
1792
1793 /* Archetype-related functions */
1794 void *
1795 cfapi_archetype_get_first (int *type, ...)
1796 {
1797 va_list args;
1798
1799 va_start (args, type);
1800 va_end (args);
1801 *type = CFAPI_PARCH;
1802 return first_archetype;
1803 }
1804
1805 void *
1806 cfapi_archetype_get_property (int *type, ...)
1807 {
1808 abort ();
1809 }
1810
1811 /* Party-related functions */
1812 void *
1813 cfapi_party_get_property (int *type, ...)
1814 {
1815 abort ();
1816 }
1817
1818 /* Regions-related functions */
1819 void *
1820 cfapi_region_get_property (int *type, ...)
1821 {
1822 abort ();
1823 }
1824
1825 /*****************************************************************************/
1826
1827 /* NEW PLUGIN STUFF ENDS HERE */
1828
1829 /*****************************************************************************/
1830
1831
1832 /*****************************************************************************/
1833
1834 /* Tries to find if a given command is handled by a plugin. */
1835
1836 /* Note that find_plugin_command is called *before* the internal commands are*/
1837
1838 /* checked, meaning that you can "overwrite" them. */
1839
1840 /*****************************************************************************/
1841 CommArray_s *
1842 find_plugin_command (char *cmd, object *op)
1843 {
1844 int i;
1845 crossfire_plugin *cp;
1846 CommArray_s *rtn_cmd;
1847
1848 if (plugins_list == NULL)
1849 return NULL;
1850
1851 for (cp = plugins_list; cp != NULL; cp = cp->next)
1852 {
1853 rtn_cmd = (CommArray_s *) cp->propfunc (&i, "command?", cmd);
1854 if (rtn_cmd)
1855 return rtn_cmd;
1856 }
1857 return NULL;
1858 }
1859
1860 /*****************************************************************************/
1861
1862 /* Plugins initialisation. Browses the plugins directory and call */
1863
1864 /* initOnePlugin for each file found. */
1865
1866 /* Returns 0 if at least one plugin was successfully loaded, -1 if not */
1867
1868 /*****************************************************************************/
1869 int
1870 initPlugins (void)
1871 {
1872 struct dirent *currentfile;
1873 DIR *plugdir;
1874 size_t l;
1875 char buf[MAX_BUF];
1876 char buf2[MAX_BUF];
1877 int result;
1878
1879 LOG (llevInfo, "Initialising plugins\n");
1880 strcpy (buf, LIBDIR);
1881 strcat (buf, "/plugins/");
1882 LOG (llevInfo, "Plugins directory is %s\n", buf);
1883
1884 plugins_init_perl ();
1885
1886 plugdir = opendir (buf);
1887 if (plugdir == NULL)
1888 return -1;
1889
1890 result = -1;
1891 while ((currentfile = readdir (plugdir)) != NULL)
1892 {
1893 l = strlen (currentfile->d_name);
1894 if (l > strlen (PLUGIN_SUFFIX))
1895 {
1896 if (strcmp (currentfile->d_name + l - strlen (PLUGIN_SUFFIX), PLUGIN_SUFFIX) == 0)
1897 {
1898 strcpy (buf2, buf);
1899 strcat (buf2, currentfile->d_name);
1900 LOG (llevInfo, " -> Loading plugin : %s\n", currentfile->d_name);
1901 if (plugins_init_plugin (buf2) == 0)
1902 result = 0;
1903 }
1904 }
1905 }
1906
1907 closedir (plugdir);
1908 return result;
1909 }