--- deliantra/server/plugins/cfperl/cfperl.xs 2006/02/17 19:36:36 1.23 +++ deliantra/server/plugins/cfperl/cfperl.xs 2006/03/06 22:59:26 1.28 @@ -31,7 +31,7 @@ #undef save_long // clashes with libproto.h #define PLUGIN_NAME "perl" -#define PLUGIN_VERSION "cfperl 0.1" +#define PLUGIN_VERSION "cfperl 0.2" #ifndef __CEXTRACT__ #include @@ -60,21 +60,21 @@ static f_plug_api map_get_map; static f_plug_api object_insert; +/* this is a stupid way to do things, and awkward to use for plug-in authors */ typedef struct { object* who; object* activator; object* third; + mapstruct* map; char message[1024]; - int fix; + int fix; // seems to be python-only, and should not be part of the API int event_code; char extension[1024]; // name field, should invoke specific perl extension char options[1024]; // slaying field of event_connectors int returnvalue; } CFPContext; -//static int current_command = -999; - static HV *obj_cache; static PerlInterpreter *perl; @@ -129,18 +129,24 @@ } static SV * +SVptr_cached (void *ptr) +{ + SV **he = hv_fetch (obj_cache, (char *)&ptr, sizeof (ptr), 0); + + return he ? *he : 0; +} + +static SV * newSVptr_cached (void *ptr, const char *klass) { - SV *sv, **he; + SV *sv; if (!ptr) return &PL_sv_undef; - he = hv_fetch (obj_cache, (char *)&ptr, sizeof (ptr), 0); + sv = SVptr_cached (ptr); - if (he) - sv = *he; - else + if (!sv) { HV *hv = newHV (); sv_magic ((SV *)hv, 0, PERL_MAGIC_ext, (char *)ptr, 0); @@ -194,6 +200,12 @@ switch (type) { +#if 0 + case CFAPI_INT16: + sv = newSViv (*va_arg (args, sint16_t *)); + break; +#endif + case CFAPI_INT: sv = newSViv (*va_arg (args, int *)); break; @@ -283,6 +295,7 @@ 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); @@ -428,6 +441,9 @@ registerGlobalEvent (NULL, EVENT_MAPENTER, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_MAPLEAVE, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_MAPRESET, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_MAPLOAD, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_MAPOUT, PLUGIN_NAME, globalEventListener); + registerGlobalEvent (NULL, EVENT_MAPIN, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_REMOVE, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_SHOUT, PLUGIN_NAME, globalEventListener); registerGlobalEvent (NULL, EVENT_TELL, PLUGIN_NAME, globalEventListener); @@ -489,6 +505,12 @@ printf ("Unimplemented for now\n"); break; + case EVENT_MAPLOAD: + case EVENT_MAPOUT: + case EVENT_MAPIN: + context.map = va_arg (args, mapstruct *); + break; + case EVENT_MAPENTER: case EVENT_MAPLEAVE: case EVENT_FREE_OB: @@ -532,6 +554,7 @@ break; case EVENT_MAPRESET: + /* stupid, should be the map itself, not "message"??? */ buf = va_arg (args, char *); if (buf != 0) strncpy (context.message, buf, sizeof (context.message)); @@ -990,6 +1013,9 @@ const_event (MAPENTER) const_event (MAPLEAVE) const_event (MAPRESET) + const_event (MAPLOAD) + const_event (MAPOUT) + const_event (MAPIN) const_event (REMOVE) const_event (SHOUT) const_event (TELL) @@ -1199,7 +1225,13 @@ } break; case CFAPI_STRING: - cf_object_set_string_property (obj, idx, SvPV_nolen (newval)); + cf_object_set_string_property (obj, idx, SvOK (newval) ? SvPV_nolen (newval) : 0); + break; + case CFAPI_POBJECT: + { + int unused_type; + object_set_property (&unused_type, obj, idx, (object *)SvPTR_ornull (newval, "cf::object")); + } break; default: croak ("unhandled type '%d' in set_property '%d'", type, idx); @@ -1501,6 +1533,7 @@ PPCODE: { object *o; + for (o = GET_MAP_OB (obj, x, y); o; o = o->above) XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o))); } @@ -1533,6 +1566,43 @@ OUTPUT: RETVAL +void +_get_obs (mapstruct *map) + PPCODE: +{ + object *o; + int x, y; + AV *obs = newAV (); + int nonnull = 0; + + for (y = 0; y < MAP_HEIGHT (map); y++) + for (x = 0; x < MAP_WIDTH (map); x++) + { + AV *av = newAV (); + + for (o = GET_MAP_OB (map, x, y); o; o = o->above) + { + SV *sv = SVptr_cached (o); + + if (sv && HvFILL (SvRV (sv))) + { + nonnull = 1; + sv = newSVsv (sv); + } + else + sv = &PL_sv_undef; + + av_push (av, sv); + } + + av_store (obs, x + y * MAP_HEIGHT (map), newRV_noinc ((SV *)av)); + } + + if (nonnull) + XPUSHs (sv_2mortal (newRV_noinc ((SV *)obs))); + else + SvREFCNT_dec (obs); +} MODULE = cf PACKAGE = cf::arch PREFIX = cf_archetype_