/*
* This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
*
* Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
* Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
* Copyright (©) 1992,2007 Frank Tore Johansen
*
* Crossfire TRT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* The authors can be reached via e-mail to
*/
/*****************************************************************************/
/* This is the server-side plugin management part. */
/*****************************************************************************/
/* Original code by Yann Chachkoff (yann.chachkoff@mailandnews.com). */
/* Special thanks to: */
/* David Delbecq (david.delbecq@mailandnews.com); */
/* Joris Bontje (jbontje@suespammers.org); */
/* Philip Currlin (?); */
/*****************************************************************************/
/*****************************************************************************/
/* First, the headers. We only include plugin.h, because all other includes */
/* are done into it, and plugproto.h (which is used only by this file). */
/*****************************************************************************/
#include
#ifndef __CEXTRACT__
# include
#endif
#define NR_OF_HOOKS 74
static const hook_entry plug_hooks[NR_OF_HOOKS] = {
{cfapi_system_register_global_event, 1, "cfapi_system_register_global_event"},
{cfapi_system_unregister_global_event, 3, "cfapi_system_unregister_global_event"},
{NULL, 4, "cfapi_system_check_path"},
{NULL, 5, "cfapi_system_re_cmp"},
{cfapi_system_strdup, 6, "cfapi_system_strdup"},
{cfapi_system_directory, 7, "cfapi_system_directory"},
{cfapi_system_find_animation, 8, "cfapi_system_find_animation"},
{cfapi_object_clean_object, 9, "cfapi_object_clean_object"},
{cfapi_object_on_same_map, 10, "cfapi_object_on_same_map"},
{cfapi_object_get_key, 11, "cfapi_object_get_key"},
{cfapi_object_set_key, 12, "cfapi_object_set_key"},
{cfapi_object_get_property, 13, "cfapi_object_get_property"},
{cfapi_object_set_property, 14, "cfapi_object_set_property"},
{cfapi_object_apply, 15, "cfapi_object_apply"},
{cfapi_object_identify, 16, "cfapi_object_identify"},
{cfapi_object_describe, 17, "cfapi_object_describe"},
{cfapi_object_drain, 18, "cfapi_object_drain"},
{cfapi_object_fix, 19, "cfapi_object_fix"},
{cfapi_object_give_skill, 20, "cfapi_object_give_skill"},
{cfapi_object_transmute, 21, "cfapi_object_transmute"},
{cfapi_object_remove, 22, "cfapi_object_remove"},
{cfapi_object_delete, 23, "cfapi_object_delete"},
{cfapi_object_clone, 24, "cfapi_object_clone"},
{cfapi_object_find, 25, "cfapi_object_find"},
{cfapi_object_create, 26, "cfapi_object_create"},
{cfapi_object_insert, 27, "cfapi_object_insert"},
{cfapi_object_split, 28, "cfapi_object_split"},
{cfapi_object_merge, 29, "cfapi_object_merge"},
{cfapi_object_distance, 30, "cfapi_object_distance"},
{cfapi_object_update, 31, "cfapi_object_update"},
{cfapi_object_clear, 32, "cfapi_object_clear"},
{cfapi_object_reset, 33, "cfapi_object_reset"},
{cfapi_object_check_inventory, 34, "cfapi_object_check_inventory"},
{cfapi_object_spring_trap, 35, "cfapi_object_spring_trap"},
{cfapi_object_check_trigger, 36, "cfapi_object_check_trigger"},
{cfapi_object_query_cost, 37, "cfapi_object_query_cost"},
{cfapi_object_query_money, 38, "cfapi_object_query_money"},
{cfapi_object_cast, 39, "cfapi_object_cast"},
{cfapi_object_learn_spell, 40, "cfapi_object_learn_spell"},
{cfapi_object_forget_spell, 41, "cfapi_object_forget_spell"},
{cfapi_object_check_spell, 42, "cfapi_object_check_spell"},
{cfapi_object_pay_amount, 43, "cfapi_object_pay_amount"},
{cfapi_object_pay_item, 44, "cfapi_object_pay_item"},
{cfapi_object_transfer, 45, "cfapi_object_transfer"},
{cfapi_object_drop, 46, "cfapi_object_drop"},
{cfapi_object_take, 47, "cfapi_object_take"},
{cfapi_object_find_archetype_inside, 48, "cfapi_object_find_archetype_inside"},
{cfapi_object_say, 49, "cfapi_object_say"},
{cfapi_map_get_map, 50, "cfapi_map_get_map"},
{cfapi_map_has_been_loaded, 51, "cfapi_map_has_been_loaded"},
{cfapi_map_create_path, 52, "cfapi_map_create_path"},
{cfapi_map_get_map_property, 53, "cfapi_map_get_property"},
{cfapi_map_set_map_property, 54, "cfapi_map_set_property"},
{cfapi_map_out_of_map, 55, "cfapi_map_out_of_map"},
{cfapi_map_update_position, 56, "cfapi_map_update_position"},
{cfapi_map_delete_map, 57, "cfapi_map_delete_map"},
{cfapi_map_message, 58, "cfapi_map_message"},
{cfapi_map_get_object_at, 59, "cfapi_map_get_object_at"},
{cfapi_map_get_flags, 60, "cfapi_map_get_flags"},
{cfapi_map_present_arch_by_name, 61, "cfapi_map_present_arch_by_name"},
{cfapi_player_find, 62, "cfapi_player_find"},
{cfapi_player_message, 63, "cfapi_player_message"},
{cfapi_player_send_inventory, 64, "cfapi_player_send_inventory"},
{cfapi_object_teleport, 65, "cfapi_object_teleport"},
{cfapi_object_speak, 66, "cfapi_object_speak"},
{cfapi_object_pickup, 67, "cfapi_object_pickup"},
{cfapi_object_move, 68, "cfapi_object_move"},
{cfapi_object_apply_below, 69, "cfapi_object_apply_below"},
{cfapi_archetype_get_first, 70, "cfapi_archetype_get_first"},
{cfapi_archetype_get_property, 71, "cfapi_archetype_get_property"},
{cfapi_party_get_property, 72, "cfapi_party_get_property"},
{cfapi_region_get_property, 73, "cfapi_region_get_property"},
};
int plugin_number = 0;
crossfire_plugin *plugins_list = NULL;
/*****************************************************************************/
/* NEW PLUGIN STUFF STARTS HERE */
/*****************************************************************************/
/**
* Notify clients about a removed object.
*
* @param op the object about to be removed from its environment; it must still
* be present in its environment
*/
static void
send_removed_object (object *op)
{
object *tmp;
if (op->env == NULL)
{
/* no action necessary: remove_ob() notifies the client */
return;
}
tmp = op->in_player ();
if (!tmp)
{
for_all_players (pl)
if (pl->ob->container == op->env)
{
tmp = pl->ob;
break;
}
}
if (tmp)
esrv_del_item (tmp->contr, op->count);
}
extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr);
extern "C" void *cfperl_getPluginProperty (int *type, ...);
extern "C" int cfperl_postInitPlugin ();
extern "C" int cfperl_closePlugin ();
// this is a temporary hack till the old plugin stuff is removed
int
plugins_init_perl ()
{
f_plug_init initfunc;
f_plug_api propfunc;
f_plug_postinit postfunc;
f_plug_postinit closefunc;
int i;
crossfire_plugin *cp;
crossfire_plugin *ccp;
initfunc = (f_plug_init) cfperl_initPlugin;
propfunc = (f_plug_api) cfperl_getPluginProperty;
postfunc = (f_plug_postinit) cfperl_postInitPlugin;
closefunc = (f_plug_postinit) cfperl_closePlugin;
i = initfunc ("2.0", cfapi_get_hooks);
cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin));
for (i = 0; i < NR_EVENTS; i++)
cp->gevent[i] = NULL;
cp->eventfunc = 0;
cp->propfunc = propfunc;
cp->closefunc = closefunc;
cp->libptr = 0;
strcpy (cp->id, (const char *) propfunc (&i, "Identification"));
strcpy (cp->fullname, (const char *) propfunc (&i, "FullName"));
cp->next = NULL;
cp->prev = NULL;
if (plugins_list == NULL)
{
plugins_list = cp;
}
else
{
for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
;
ccp->next = cp;
cp->prev = ccp;
}
postfunc ();
plugin_number++;
return 0;
}
int
plugins_init_plugin (const char *libfile)
{
return 0;
LIBPTRTYPE ptr;
f_plug_init initfunc;
f_plug_api propfunc;
f_plug_api eventfunc;
f_plug_postinit postfunc;
f_plug_postinit closefunc;
int i;
crossfire_plugin *cp;
crossfire_plugin *ccp;
/* Open the plugin lib and load the required functions */
ptr = plugins_dlopen (libfile);
if (ptr == NULL)
{
LOG (llevError, "Error trying to load %s: %s\n", libfile, plugins_dlerror ());
return -1;
}
initfunc = (f_plug_init) plugins_dlsym (ptr, "initPlugin");
if (initfunc == NULL)
{
LOG (llevError, "Plugin error while requesting %s.initPlugin: %s\n", libfile, plugins_dlerror ());
plugins_dlclose (ptr);
return -1;
}
propfunc = (f_plug_api) plugins_dlsym (ptr, "getPluginProperty");
if (propfunc == NULL)
{
LOG (llevError, "Plugin error while requesting %s.getPluginProperty: %s\n", libfile, plugins_dlerror ());
plugins_dlclose (ptr);
return -1;
}
eventfunc = (f_plug_api) plugins_dlsym (ptr, "eventListener");
if (eventfunc == NULL)
{
LOG (llevError, "Plugin error while requesting %s.eventListener: %s\n", libfile, plugins_dlerror ());
plugins_dlclose (ptr);
return -1;
}
postfunc = (f_plug_postinit) plugins_dlsym (ptr, "postInitPlugin");
if (postfunc == NULL)
{
LOG (llevError, "Plugin error while requesting %s.postInitPlugin: %s\n", libfile, plugins_dlerror ());
plugins_dlclose (ptr);
return -1;
}
closefunc = (f_plug_postinit) plugins_dlsym (ptr, "closePlugin");
if (postfunc == NULL)
{
LOG (llevError, "Plugin error while requesting %s.closePlugin: %s\n", libfile, plugins_dlerror ());
plugins_dlclose (ptr);
return -1;
}
i = initfunc ("2.0", cfapi_get_hooks);
cp = (crossfire_plugin *) malloc (sizeof (crossfire_plugin));
for (i = 0; i < NR_EVENTS; i++)
cp->gevent[i] = NULL;
cp->eventfunc = eventfunc;
cp->propfunc = propfunc;
cp->closefunc = closefunc;
cp->libptr = ptr;
strcpy (cp->id, (const char *) propfunc (&i, "Identification"));
strcpy (cp->fullname, (const char *) propfunc (&i, "FullName"));
cp->next = NULL;
cp->prev = NULL;
if (plugins_list == NULL)
{
plugins_list = cp;
}
else
{
for (ccp = plugins_list; ccp->next != NULL; ccp = ccp->next)
;
ccp->next = cp;
cp->prev = ccp;
}
postfunc ();
plugin_number++;
return 0;
}
void *
cfapi_get_hooks (int *type, ...)
{
va_list args;
int request_type;
char *buf;
int fid;
f_plug_api rv;
int i;
va_start (args, type);
request_type = va_arg (args, int);
if (request_type == 0)
{ /* By nr */
fid = va_arg (args, int);
if (fid < 0 || fid >= NR_OF_HOOKS)
{
rv = NULL;
*type = CFAPI_NONE;
}
else
{
rv = plug_hooks[fid].func;
*type = CFAPI_FUNC;
}
}
else
{ /* by name */
buf = va_arg (args, char *);
rv = NULL;
for (i = 0; i < NR_OF_HOOKS; i++)
{
if (!strcmp (buf, plug_hooks[i].fname))
{
rv = plug_hooks[i].func;
*type = CFAPI_FUNC;
break;
}
}
if (rv == NULL)
{
*type = CFAPI_NONE;
}
}
va_end (args);
return (void *) rv;
}
int
plugins_remove_plugin (const char *id)
{
crossfire_plugin *cp;
if (plugins_list == NULL)
return -1;
for (cp = plugins_list; cp != NULL; cp = cp->next)
{
if (!strcmp (id, cp->id) && cp->libptr)
{
crossfire_plugin *n;
crossfire_plugin *p;
n = cp->next;
p = cp->prev;
plugins_dlclose (cp->libptr);
if (n != NULL)
{
if (p != NULL)
{
n->prev = p;
p->next = n;
}
else
{
n->prev = NULL;
plugins_list = n;
}
}
else
{
if (p != NULL)
p->next = NULL;
else
plugins_list = NULL;
}
free (cp);
plugin_number--;
return 0;
}
}
return -1;
}
crossfire_plugin *
plugins_find_plugin (const char *id)
{
crossfire_plugin *cp;
if (plugins_list == NULL)
return NULL;
for (cp = plugins_list; cp != NULL; cp = cp->next)
{
if (!strcmp (id, cp->id))
{
return cp;
}
}
return NULL;
}
/*****************************************************************************/
/* Displays a list of loaded plugins (keystrings and description) in the */
/* game log window. */
/*****************************************************************************/
void
plugins_display_list (object *op)
{
crossfire_plugin *cp;
new_draw_info (NDI_UNIQUE, 0, op, "List of loaded plugins:");
new_draw_info (NDI_UNIQUE, 0, op, "-----------------------");
if (plugins_list == NULL)
return;
for (cp = plugins_list; cp != NULL; cp = cp->next)
{
new_draw_info_format (NDI_UNIQUE, 0, op, "%s, %s", cp->id, cp->fullname);
}
}
/* SYSTEM-RELATED HOOKS */
void *
cfapi_system_find_animation (int *type, ...)
{
va_list args;
static int rv;
char *anim;
va_start (args, type);
anim = va_arg (args, char *);
va_end (args);
rv = find_animation (anim);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_system_strdup (int *type, ...)
{
va_list args;
char *txt;
va_start (args, type);
txt = va_arg (args, char *);
va_end (args);
*type = CFAPI_STRING;
return strdup (txt);
}
void *
cfapi_system_register_global_event (int *type, ...)
{
va_list args;
int eventcode;
char *pname;
f_plug_api hook;
crossfire_plugin *cp;
va_start (args, type);
eventcode = va_arg (args, int);
pname = va_arg (args, char *);
hook = va_arg (args, f_plug_api);
va_end (args);
cp = plugins_find_plugin (pname);
cp->gevent[eventcode] = hook;
return NULL;
}
void *
cfapi_system_unregister_global_event (int *type, ...)
{
va_list args;
int eventcode;
char *pname;
crossfire_plugin *cp;
va_start (args, type);
eventcode = va_arg (args, int);
pname = va_arg (args, char *);
cp = plugins_find_plugin (pname);
cp->gevent[eventcode] = NULL;
va_end (args);
return NULL;
}
void *
cfapi_system_check_path (int *type, ...)
{
abort ();
}
void *
cfapi_system_directory (int *type, ...)
{
va_list args;
int dirtype;
va_start (args, type);
dirtype = va_arg (args, int);
va_end (args);
*type = CFAPI_STRING;
switch (dirtype)
{
case 0:
return (char *)settings.mapdir;
break;
case 1:
return (char *)settings.uniquedir;
break;
case 2:
return (char *)settings.tmpdir;
break;
case 3:
return (char *)settings.confdir;
break;
case 4:
return (char *)settings.localdir;
break;
case 5:
return (char *)settings.playerdir;
break;
case 6:
return (char *)settings.datadir;
break;
}
*type = CFAPI_NONE;
return NULL;
}
/* MAP RELATED HOOKS */
void *
cfapi_map_get_map (int *type, ...)
{
abort ();
}
void *
cfapi_map_has_been_loaded (int *type, ...)
{
abort ();
}
void *
cfapi_map_create_path (int *type, ...)
{
abort ();
}
void *
cfapi_map_get_map_property (int *type, ...)
{
abort ();
}
void *
cfapi_map_set_map_property (int *type, ...)
{
abort ();
}
void *
cfapi_map_out_of_map (int *type, ...)
{
abort ();
}
void *
cfapi_map_update_position (int *type, ...)
{
va_list args;
maptile *map;
int x, y;
va_start (args, type);
map = va_arg (args, maptile *);
x = va_arg (args, int);
y = va_arg (args, int);
map->at (x, y).flags_ &= ~P_UPTODATE;
va_end (args);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_map_delete_map (int *type, ...)
{
abort ();
}
void *
cfapi_map_message (int *type, ...)
{
va_list args;
maptile *map;
char *string;
int color;
va_start (args, type);
map = va_arg (args, maptile *);
string = va_arg (args, char *);
color = va_arg (args, int);
va_end (args);
new_info_map (color, map, string);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_map_get_object_at (int *type, ...)
{
va_list args;
maptile *map;
int x, y;
object *rv;
va_start (args, type);
map = va_arg (args, maptile *);
x = va_arg (args, int);
y = va_arg (args, int);
va_end (args);
rv = GET_MAP_OB (map, x, y);
*type = CFAPI_POBJECT;
return rv;
}
void *
cfapi_map_get_flags (int *type, ...)
{
va_list args;
sint16 x, y;
sint16 *nx, *ny;
static maptile *map;
maptile **newmap;
static int rv;
va_start (args, type);
map = va_arg (args, maptile *);
newmap = va_arg (args, maptile **);
x = va_arg (args, int);
y = va_arg (args, int);
nx = va_arg (args, sint16 *);
ny = va_arg (args, sint16 *);
va_end (args);
rv = get_map_flags (map, newmap, x, y, nx, ny);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_map_present_arch_by_name (int *type, ...)
{
va_list args;
object *rv;
int x, y;
maptile *map;
char *msg;
va_start (args, type);
msg = va_arg (args, char *);
map = va_arg (args, maptile *);
x = va_arg (args, int);
y = va_arg (args, int);
va_end (args);
rv = present_arch (archetype::find (msg), map, x, y);
*type = CFAPI_POBJECT;
return rv;
}
/* OBJECT-RELATED HOOKS */
void *
cfapi_object_move (int *type, ...)
{
va_list args;
int kind;
object *op;
object *activator;
player *pl;
int direction;
static int rv = 0;
va_start (args, type);
kind = va_arg (args, int);
switch (kind)
{
case 0:
op = va_arg (args, object *);
direction = va_arg (args, int);
activator = va_arg (args, object *);
va_end (args);
rv = move_ob (op, direction, activator);
break;
case 1:
pl = va_arg (args, player *);
direction = va_arg (args, int);
va_end (args);
rv = move_player (pl->ob, direction);
break;
}
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_get_key (int *type, ...)
{
va_list args;
char *rv;
char *keyname;
object *op;
va_start (args, type);
op = va_arg (args, object *);
keyname = va_arg (args, char *);
va_end (args);
rv = (char *) get_ob_key_value (op, keyname);
*type = CFAPI_STRING;
return rv;
}
void *
cfapi_object_set_key (int *type, ...)
{
va_list args;
char *keyname;
char *value;
object *op;
va_start (args, type);
op = va_arg (args, object *);
keyname = va_arg (args, char *);
value = va_arg (args, char *);
va_end (args);
set_ob_key_value (op, keyname, value, 0);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_get_property (int *type, ...)
{
abort ();
}
void *
cfapi_object_set_property (int *type, ...)
{
abort ();
}
void *
cfapi_object_apply_below (int *type, ...)
{
va_list args;
object *applier;
va_start (args, type);
applier = va_arg (args, object *);
va_end (args);
player_apply_below (applier);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_apply (int *type, ...)
{
va_list args;
object *applied;
object *applier;
int aflags;
static int rv;
va_start (args, type);
applied = va_arg (args, object *);
applier = va_arg (args, object *);
aflags = va_arg (args, int);
va_end (args);
*type = CFAPI_INT;
rv = manual_apply (applier, applied, aflags);
return &rv;
}
void *
cfapi_object_identify (int *type, ...)
{
va_list args;
object *op;
va_start (args, type);
op = va_arg (args, object *);
va_end (args);
identify (op);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_describe (int *type, ...)
{
va_list args;
object *op;
object *owner;
va_start (args, type);
op = va_arg (args, object *);
owner = va_arg (args, object *);
va_end (args);
*type = CFAPI_STRING;
return (char *)describe_item (op, owner);
}
void *
cfapi_object_drain (int *type, ...)
{
abort ();
}
void *
cfapi_object_fix (int *type, ...)
{
va_list args;
object *op;
va_start (args, type);
op = va_arg (args, object *);
va_end (args);
op->update_stats ();
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_give_skill (int *type, ...)
{
va_list args;
object *op;
char *skillname;
va_start (args, type);
op = va_arg (args, object *);
skillname = va_arg (args, char *);
va_end (args);
*type = CFAPI_POBJECT;
return give_skill_by_name (op, skillname);
}
void *
cfapi_object_transmute (int *type, ...)
{
va_list args;
object *op;
object *chg;
va_start (args, type);
op = va_arg (args, object *);
chg = va_arg (args, object *);
va_end (args);
transmute_materialname (op, chg);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_remove (int *type, ...)
{
va_list args;
object *op;
va_start (args, type);
op = va_arg (args, object *);
va_end (args);
send_removed_object (op);
op->remove ();
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_delete (int *type, ...)
{
va_list args;
object *op;
va_start (args, type);
op = va_arg (args, object *);
va_end (args);
op->destroy ();
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_clone (int *type, ...)
{
va_list args;
object *op;
int kind;
va_start (args, type);
op = va_arg (args, object *);
kind = va_arg (args, int);
va_end (args);
if (kind == 0)
{
*type = CFAPI_POBJECT;
return object_create_clone (op);
}
else
{
object *tmp = op->clone ();
*type = CFAPI_POBJECT;
return tmp;
}
}
void *
cfapi_object_find (int *type, ...)
{
va_list args;
int ftype;
void *rv;
int ival;
int ival2;
char *sval;
object *op;
va_start (args, type);
*type = CFAPI_POBJECT;
ftype = va_arg (args, int);
switch (ftype)
{
case 0:
ival = va_arg (args, int);
rv = find_object (ival);
break;
case 1:
sval = va_arg (args, char *);
rv = find_object_name (sval);
break;
case 2:
op = va_arg (args, object *);
ival = va_arg (args, int);
ival2 = va_arg (args, int);
rv = find_obj_by_type_subtype (op, ival, ival2);
break;
case 3:
op = va_arg (args, object *);
rv = op->in_player ();
break;
default:
rv = NULL;
*type = CFAPI_NONE;
break;
}
va_end (args);
return rv;
}
void *
cfapi_object_create (int *type, ...)
{
abort ();
}
void *
cfapi_object_insert (int *type, ...)
{
va_list args;
object *op;
object *orig;
maptile *map;
int flag, x, y;
int itype;
char *arch_string;
void *rv = NULL;
va_start (args, type);
op = va_arg (args, object *);
itype = va_arg (args, int);
switch (itype)
{
case 0:
map = va_arg (args, maptile *);
orig = va_arg (args, object *);
flag = va_arg (args, int);
x = va_arg (args, int);
y = va_arg (args, int);
rv = insert_ob_in_map_at (op, map, orig, flag, x, y);
*type = CFAPI_POBJECT;
break;
case 1:
map = va_arg (args, maptile *);
orig = va_arg (args, object *);
flag = va_arg (args, int);
rv = insert_ob_in_map (op, map, orig, flag);
*type = CFAPI_POBJECT;
break;
case 2:
arch_string = va_arg (args, char *);
replace_insert_ob_in_map (arch_string, op);
*type = CFAPI_NONE;
break;
case 3:
orig = va_arg (args, object *);
rv = insert_ob_in_ob (op, orig);
if (orig->type == PLAYER)
{
esrv_send_item (orig, op);
}
*type = CFAPI_POBJECT;
break;
}
va_end (args);
return rv;
}
void *
cfapi_object_split (int *type, ...)
{
va_list args;
int nr;
object *op;
va_start (args, type);
op = va_arg (args, object *);
nr = va_arg (args, int);
va_end (args);
*type = CFAPI_POBJECT;
return get_split_ob (op, nr);
}
void *
cfapi_object_merge (int *type, ...)
{
va_list args;
object *op;
object *op2;
va_start (args, type);
op = va_arg (args, object *);
op2 = va_arg (args, object *);
va_end (args);
*type = CFAPI_POBJECT;
return merge_ob (op, op2);
}
void *
cfapi_object_distance (int *type, ...)
{
va_list args;
static int rv;
object *op;
object *op2;
va_start (args, type);
op = va_arg (args, object *);
op2 = va_arg (args, object *);
va_end (args);
*type = CFAPI_INT;
rv = distance (op, op2);
return &rv;
}
void *
cfapi_object_update (int *type, ...)
{
va_list args;
int action;
object *op;
va_start (args, type);
op = va_arg (args, object *);
action = va_arg (args, int);
va_end (args);
update_object (op, action);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_clear (int *type, ...)
{
abort ();
}
void *
cfapi_object_reset (int *type, ...)
{
abort ();
}
void *
cfapi_object_check_inventory (int *type, ...)
{
va_list args;
object *op;
object *op2;
int checktype;
object *ret = NULL;
va_start (args, type);
op = va_arg (args, object *);
op2 = va_arg (args, object *);
checktype = va_arg (args, int);
if (checktype == 0)
{
check_inv (op, op2);
*type = CFAPI_NONE;
}
else
{
ret = check_inv_recursive (op, op2);
*type = CFAPI_POBJECT;
}
va_end (args);
return ret;
}
void *
cfapi_object_clean_object (int *type, ...)
{
abort ();
}
void *
cfapi_object_on_same_map (int *type, ...)
{
va_list args;
static int rv;
object *op1;
object *op2;
va_start (args, type);
op1 = va_arg (args, object *);
op2 = va_arg (args, object *);
rv = on_same_map (op1, op2);
va_end (args);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_spring_trap (int *type, ...)
{
object *trap;
object *victim;
va_list args;
va_start (args, type);
trap = va_arg (args, object *);
victim = va_arg (args, object *);
va_end (args);
spring_trap (trap, victim);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_check_trigger (int *type, ...)
{
object *op;
object *cause;
va_list args;
static int rv;
va_start (args, type);
op = va_arg (args, object *);
cause = va_arg (args, object *);
va_end (args);
rv = check_trigger (op, cause);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_query_cost (int *type, ...)
{
object *op;
object *who;
int flags;
va_list args;
static int rv;
va_start (args, type);
op = va_arg (args, object *);
who = va_arg (args, object *);
flags = va_arg (args, int);
va_end (args);
rv = query_cost (op, who, flags);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_query_money (int *type, ...)
{
object *op;
va_list args;
static int rv;
va_start (args, type);
op = va_arg (args, object *);
va_end (args);
rv = query_money (op);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_cast (int *type, ...)
{
object *op;
object *sp;
int dir;
char *str;
object *caster;
va_list args;
static int rv;
va_start (args, type);
op = va_arg (args, object *);
caster = va_arg (args, object *);
dir = va_arg (args, int);
sp = va_arg (args, object *);
str = va_arg (args, char *);
va_end (args);
rv = cast_spell (op, caster, dir, sp, str);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_learn_spell (int *type, ...)
{
object *op;
object *sp;
int prayer;
va_list args;
va_start (args, type);
op = va_arg (args, object *);
sp = va_arg (args, object *);
prayer = va_arg (args, int);
va_end (args);
do_learn_spell (op, sp, prayer);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_forget_spell (int *type, ...)
{
object *op;
object *sp;
va_list args;
va_start (args, type);
op = va_arg (args, object *);
sp = va_arg (args, object *);
va_end (args);
do_forget_spell (op, query_name (sp));
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_check_spell (int *type, ...)
{
object *op;
char *spellname;
va_list args;
object *rv;
va_start (args, type);
op = va_arg (args, object *);
spellname = va_arg (args, char *);
va_end (args);
rv = check_spell_known (op, spellname);
*type = CFAPI_POBJECT;
return rv;
}
void *
cfapi_object_pay_amount (int *type, ...)
{
object *op;
uint64 amount;
va_list args;
static int rv;
va_start (args, type);
op = va_arg (args, object *);
amount = va_arg (args, uint64);
va_end (args);
rv = pay_for_amount (amount, op);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_pay_item (int *type, ...)
{
object *op;
object *tobuy;
va_list args;
static int rv;
va_start (args, type);
tobuy = va_arg (args, object *);
op = va_arg (args, object *);
va_end (args);
rv = pay_for_item (tobuy, op);
*type = CFAPI_INT;
return &rv;
}
void *
cfapi_object_transfer (int *type, ...)
{
object *op;
object *originator;
int x, y, randompos, ttype;
va_list args;
static int rv = 0;
maptile *map;
va_start (args, type);
op = va_arg (args, object *);
ttype = va_arg (args, int);
switch (ttype)
{
case 0:
x = va_arg (args, int);
y = va_arg (args, int);
randompos = va_arg (args, int);
originator = va_arg (args, object *);
va_end (args);
rv = transfer_ob (op, x, y, randompos, originator);
*type = CFAPI_INT;
return &rv;
break;
case 1:
x = va_arg (args, int);
y = va_arg (args, int);
map = va_arg (args, maptile *);
va_end (args);
if (x < 0 || y < 0)
{
x = map->enter_x;
y = map->enter_y;
}
/*
originator = object::create();
EXIT_PATH(originator) = map->path;
EXIT_X(originator) = x;
EXIT_Y(originator) = y;
printf("B Transfer: X=%d, Y=%d, OP=%s\n", x, y, op->name);*/
/*enter_exit(op, originator); */
insert_ob_in_map_at (op, map, NULL, 0, x, y);
/*printf("A Transfer: X=%d, Y=%d, MAP=%s\n", x, y, op->map->name);
originator->destroy ();
*/
*type = CFAPI_INT;
return &rv;
break;
default:
*type = CFAPI_NONE;
return NULL;
break;
}
}
void *
cfapi_object_find_archetype_inside (int *type, ...)
{
object *op;
int critera;
char *str;
va_list args;
object *rv;
*type = CFAPI_POBJECT;
va_start (args, type);
op = va_arg (args, object *);
critera = va_arg (args, int);
switch (critera)
{
case 0: /* By name, either exact or from query_name */
str = va_arg (args, char *);
rv = present_arch_in_ob (archetype::find (str), op);
if (rv == NULL)
{
object *tmp;
/* Search by query_name instead */
for (tmp = op->inv; tmp; tmp = tmp->below)
{
if (!strncmp (query_name (tmp), str, strlen (str)))
rv = tmp;
if (!strncmp (tmp->name, str, strlen (str)))
rv = tmp;
if (rv != NULL)
break;
}
}
break;
default:
rv = NULL;
break;
}
va_end (args);
if (rv == NULL)
{
*type = CFAPI_NONE;
}
return rv;
}
void *
cfapi_object_drop (int *type, ...)
{
object *op;
object *author;
va_list args;
va_start (args, type);
op = va_arg (args, object *);
author = va_arg (args, object *);
va_end (args);
if (QUERY_FLAG (op, FLAG_NO_DROP))
return NULL;
drop (author, op);
if (author->type == PLAYER)
{
author->contr->count = 0;
author->contr->ns->floorbox_update ();
}
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_take (int *type, ...)
{
object *op;
object *author;
va_list args;
va_start (args, type);
op = va_arg (args, object *);
author = va_arg (args, object *);
va_end (args);
pick_up (author, op);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_say (int *type, ...)
{
abort ();
}
void *
cfapi_object_speak (int *type, ...)
{
abort ();
}
/* PLAYER SUBCLASS */
void *
cfapi_player_find (int *type, ...)
{
abort ();
}
void *
cfapi_player_message (int *type, ...)
{
va_list args;
int flags;
int pri;
object *pl;
char *buf;
va_start (args, type);
flags = va_arg (args, int);
pri = va_arg (args, int);
pl = va_arg (args, object *);
buf = va_arg (args, char *);
va_end (args);
new_draw_info (flags, pri, pl, buf);
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_player_send_inventory (int *type, ...)
{
/* Currently a stub. Do we really need this anymore ? */
*type = CFAPI_NONE;
return NULL;
}
void *
cfapi_object_teleport (int *type, ...)
{
maptile *map;
int x, y;
object *who;
static int result;
va_list args;
va_start (args, type);
who = va_arg (args, object *);
map = va_arg (args, maptile *);
x = va_arg (args, int);
y = va_arg (args, int);
if (!out_of_map (map, x, y))
{
int k;
object *tmp;
k = find_first_free_spot (who, map, x, y);
if (k == -1)
{
result = 1;
return &result;
}
send_removed_object (who);
who->remove ();
for (tmp = who; tmp != NULL; tmp = tmp->more)
tmp->x = x + freearr_x[k] + (tmp->arch == NULL ? 0 : tmp->arch->x),
tmp->y = y + freearr_y[k] + (tmp->arch == NULL ? 0 : tmp->arch->y);
insert_ob_in_map (who, map, NULL, 0);
result = 0;
}
return &result;
}
void *
cfapi_object_pickup (int *type, ...)
{
object *who;
object *what;
va_list args;
va_start (args, type);
who = va_arg (args, object *);
what = va_arg (args, object *);
va_end (args);
pick_up (who, what);
*type = CFAPI_NONE;
return NULL;
}
/* Archetype-related functions */
void *
cfapi_archetype_get_first (int *type, ...)
{
abort ();
}
void *
cfapi_archetype_get_property (int *type, ...)
{
abort ();
}
/* Party-related functions */
void *
cfapi_party_get_property (int *type, ...)
{
abort ();
}
/* Regions-related functions */
void *
cfapi_region_get_property (int *type, ...)
{
abort ();
}
/*****************************************************************************/
/* NEW PLUGIN STUFF ENDS HERE */
/*****************************************************************************/
/*****************************************************************************/
/* Tries to find if a given command is handled by a plugin. */
/* Note that find_plugin_command is called *before* the internal commands are*/
/* checked, meaning that you can "overwrite" them. */
/*****************************************************************************/
CommArray_s *
find_plugin_command (char *cmd, object *op)
{
int i;
crossfire_plugin *cp;
CommArray_s *rtn_cmd;
if (plugins_list == NULL)
return NULL;
for (cp = plugins_list; cp != NULL; cp = cp->next)
{
rtn_cmd = (CommArray_s *) cp->propfunc (&i, "command?", cmd);
if (rtn_cmd)
return rtn_cmd;
}
return NULL;
}
/*****************************************************************************/
/* Plugins initialisation. Browses the plugins directory and call */
/* initOnePlugin for each file found. */
/* Returns 0 if at least one plugin was successfully loaded, -1 if not */
/*****************************************************************************/
int
initPlugins (void)
{
struct dirent *currentfile;
DIR *plugdir;
size_t l;
char buf[MAX_BUF];
char buf2[MAX_BUF];
int result;
LOG (llevInfo, "Initialising plugins\n");
strcpy (buf, LIBDIR);
strcat (buf, "/plugins/");
LOG (llevInfo, "Plugins directory is %s\n", buf);
plugins_init_perl ();
plugdir = opendir (buf);
if (plugdir == NULL)
return -1;
result = -1;
while ((currentfile = readdir (plugdir)) != NULL)
{
l = strlen (currentfile->d_name);
if (l > strlen (PLUGIN_SUFFIX))
{
if (strcmp (currentfile->d_name + l - strlen (PLUGIN_SUFFIX), PLUGIN_SUFFIX) == 0)
{
strcpy (buf2, buf);
strcat (buf2, currentfile->d_name);
LOG (llevInfo, " -> Loading plugin : %s\n", currentfile->d_name);
if (plugins_init_plugin (buf2) == 0)
result = 0;
}
}
}
closedir (plugdir);
return result;
}