--- deliantra/server/plugins/cfperl/cfperl.xs 2006/03/28 16:48:12 1.42 +++ deliantra/server/plugins/cfperl/cfperl.xs 2006/04/02 15:57:54 1.47 @@ -1,6 +1,5 @@ /*****************************************************************************/ /* CrossFire, A Multiplayer game for the X Window System */ -/* */ /*****************************************************************************/ /* @@ -31,7 +30,7 @@ #undef save_long // clashes with libproto.h #define PLUGIN_NAME "perl" -#define PLUGIN_VERSION "cfperl 0.2" +#define PLUGIN_VERSION "cfperl 0.3" #ifndef __CEXTRACT__ #include @@ -67,6 +66,7 @@ object* who; object* activator; object* third; + object* event; mapstruct* map; char message[1024]; int fix; // seems to be python-only, and should not be part of the API @@ -79,12 +79,13 @@ static HV *obj_cache; static PerlInterpreter *perl; -#define PUSHcfapi(type,ctype) PUSHs (sv_2mortal (newSVcfapi ((type), va_arg (args, ctype)))) -#define PUSH_OB PUSHcfapi(CFAPI_POBJECT, object *) -#define PUSH_PL PUSHcfapi(CFAPI_PPLAYER, player *) -#define PUSH_MAP PUSHcfapi(CFAPI_PMAP, mapstruct *) -#define PUSH_PV PUSHcfapi(CFAPI_STRING, const char *) -#define PUSH_IV PUSHcfapi(CFAPI_INT, int) +#define PUSHcfapi(type,value) PUSHs (sv_2mortal (newSVcfapi (CFAPI_ ## type, (value)))) +#define PUSHcfapi_va(type,ctype) PUSHcfapi (type, va_arg (args, ctype)) +#define PUSH_OB PUSHcfapi_va(POBJECT, object *) +#define PUSH_PL PUSHcfapi_va(PPLAYER, player *) +#define PUSH_MAP PUSHcfapi_va(PMAP, mapstruct *) +#define PUSH_PV PUSHcfapi_va(STRING, const char *) +#define PUSH_IV PUSHs (sv_2mortal (newSViv (va_arg (args, int)))) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -230,7 +231,7 @@ break; case CFAPI_DOUBLE: - sv = newSViv (*va_arg (args, double *)); + sv = newSVnv (*va_arg (args, double *)); break; case CFAPI_STRING: @@ -247,7 +248,7 @@ if (!obj) sv = &PL_sv_undef; else - switch (*(int *)cf_object_get_property (obj, CFAPI_OBJECT_PROP_TYPE)) + switch (obj->type) { case MAP: sv = newSVptr_cached (obj, "cf::object::map"); @@ -295,48 +296,6 @@ ///////////////////////////////////////////////////////////////////////////// -void -inject_event (const char *func, CFPContext *context) -{ - dSP; - - ENTER; - SAVETMPS; - - PUSHMARK (SP); - - EXTEND (SP, 10); - - HV *hv = newHV (); -#define hv_context(type,addr,expr) hv_store (hv, #expr, sizeof (#expr) - 1, newSVcfapi (type, addr context->expr), 0) - hv_context (CFAPI_POBJECT, ,who); - hv_context (CFAPI_POBJECT, ,activator); - hv_context (CFAPI_POBJECT, ,third); - hv_context (CFAPI_PMAP, ,map); - hv_context (CFAPI_STRING , ,message); - hv_context (CFAPI_INT ,&,fix); - hv_context (CFAPI_INT ,&,event_code); - hv_context (CFAPI_STRING , ,options); - hv_context (CFAPI_STRING , ,extension); - - PUSHs (sv_2mortal (newRV_noinc ((SV *)hv))); - - PUTBACK; - int count = call_pv (func, G_SCALAR | G_EVAL); - SPAGAIN; - - if (SvTRUE (ERRSV)) - LOG (llevError, "event '%d' callback evaluation error: %s", context->event_code, SvPV_nolen (ERRSV)); - - context->returnvalue = count > 0 ? POPi : 0; - - PUTBACK; - FREETMPS; - LEAVE; -} - -///////////////////////////////////////////////////////////////////////////// - int initPlugin (const char *iversion, f_plug_api gethooksptr) { @@ -600,7 +559,7 @@ SPAGAIN; if (SvTRUE (ERRSV)) - LOG (llevError, "event '%d' callback evaluation error: %s", event_code, SvPV_nolen (ERRSV)); + LOG (llevError, "global event '%d' callback evaluation error: %s", event_code, SvPV_nolen (ERRSV)); rv = count > 0 ? POPi : 0; @@ -615,38 +574,93 @@ void * eventListener (int *type, ...) { - static int rv = 0; + static int rv; va_list args; - char *buf; - CFPContext context; - object *eob; + int event_code; + object *who, *activator, *third, *event; + char *message, *extension, *options; if (!perl) return; - memset (&context, 0, sizeof (context)); - va_start (args, type); - - context.who = va_arg (args, object *); - context.event_code = va_arg (args, int); - context.activator = va_arg (args, object *); - context.third = va_arg (args, object *); - - buf = va_arg (args, char *); - if (buf != 0) - strncpy (context.message, buf, sizeof (context.message)); - - context.fix = va_arg (args, int); - strncpy (context.extension, va_arg (args, char *), sizeof (context.extension)); - strncpy (context.options, va_arg (args, char *), sizeof (context.options)); - eob = va_arg (args, object *); - context.returnvalue = 0; + who = va_arg (args, object *); + event_code = va_arg (args, int); + activator = va_arg (args, object *); + third = va_arg (args, object *); + message = va_arg (args, char *); + va_arg (args, int); // fix yourself + extension = va_arg (args, char *); + options = va_arg (args, char *); + event = va_arg (args, object *); va_end (args); - inject_event ("cf::inject_event", &context); + { + dSP; + + ENTER; + SAVETMPS; + + PUSHMARK (SP); + EXTEND (SP, 10); + + PUSHcfapi (STRING, extension); + PUSHs (sv_2mortal (newSViv (event_code))); + + PUSHcfapi (POBJECT, event); + PUSHcfapi (POBJECT, who); + + switch (event_code) + { + case EVENT_STOP: // $ob (e.g. arrow) + case EVENT_TIME: // $ob + case EVENT_TIMER: // $ob + break; + + case EVENT_APPLY: // $ob, $who + case EVENT_DROP: // $ob, $who + case EVENT_CLOSE: // $ob, $who + case EVENT_DEATH: // $ob[, $killer] + case EVENT_MOVE: // $ob, $enemy + case EVENT_THROW: // $ob, $thrower + PUSHcfapi (POBJECT, activator); + break; + + case EVENT_ATTACK: // $ob, $who, $victim (?? please god enlighten me) + PUSHcfapi (POBJECT, activator); + PUSHcfapi (POBJECT, third); + break; + + case EVENT_TRIGGER: // $ob, $originator, [$victim], [$msg] + PUSHcfapi (POBJECT, activator); + PUSHcfapi (POBJECT, third); + PUSHcfapi (POBJECT, message); + break; + + case EVENT_SAY: // $ob, $who, $msg + PUSHcfapi (POBJECT, activator); + PUSHcfapi (STRING, message); + break; + + default: + LOG (llevError, "perl plugin called for unsupported event type %d", event_code); + break; + } + + PUTBACK; + int count = call_pv ("cf::inject_event", G_SCALAR | G_EVAL); + SPAGAIN; + + if (SvTRUE (ERRSV)) + LOG (llevError, "event '%d' callback evaluation error: %s", event_code, SvPV_nolen (ERRSV)); + + rv = count > 0 ? POPi : 0; + + PUTBACK; + FREETMPS; + LEAVE; + } - rv = context.returnvalue; return &rv; } @@ -1511,6 +1525,13 @@ RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y); } +# syntatic sugar for easier use in event callbacks. +const char *options (object *op) + CODE: + RETVAL = op->name; + OUTPUT: + RETVAL + const char *get_ob_key_value (object *op, const char *key) bool set_ob_key_value (object *op, const char *key, const char *value = 0, int add_key = 1) @@ -1556,7 +1577,7 @@ player *player (object *op) CODE: - RETVAL = cf_player_find (cf_query_name (op)); + RETVAL = op->contr; OUTPUT: RETVAL void cf_player_message (object *obj, char *txt, int flags = NDI_ORANGE | NDI_UNIQUE) @@ -1636,6 +1657,16 @@ XPUSHs (newSVcfapi (CFAPI_PPLAYER, pl)); } +bool +peaceful (player *pl, bool new_setting = 0) + PROTOTYPE: $;$ + CODE: + RETVAL = pl->peaceful; + if (items > 1) + pl->peaceful = new_setting; + OUTPUT: + RETVAL + living * orig_stats (player *pl) CODE: