… | |
… | |
99 | #define PUSH_PV PUSHcfapi_va(STRING, const char *) |
99 | #define PUSH_PV PUSHcfapi_va(STRING, const char *) |
100 | #define PUSH_IV PUSHs (sv_2mortal (newSViv (va_arg (args, int)))) |
100 | #define PUSH_IV PUSHs (sv_2mortal (newSViv (va_arg (args, int)))) |
101 | |
101 | |
102 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
102 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
103 | |
103 | |
104 | // garbage collect some perl objects, if possible |
|
|
105 | // all objects no longer referenced and empty are |
|
|
106 | // eligible for destruction. |
|
|
107 | static void |
|
|
108 | clean_obj_cache () |
|
|
109 | { |
|
|
110 | static int count; |
|
|
111 | |
|
|
112 | if (++count & 7) |
|
|
113 | return; |
|
|
114 | |
|
|
115 | int todo = 1000; |
|
|
116 | do |
|
|
117 | { |
|
|
118 | I32 klen; |
|
|
119 | char *key; |
|
|
120 | HE *he = hv_iternext (obj_cache); |
|
|
121 | |
|
|
122 | if (he) |
|
|
123 | { |
|
|
124 | SV *sv = hv_iterval (obj_cache, he); |
|
|
125 | |
|
|
126 | // empty and unreferenced? nuke it |
|
|
127 | if (SvREFCNT (sv) == 1 && SvREFCNT (SvRV (sv)) == 1 && !HvFILL ((HV *)(SvRV (sv)))) |
|
|
128 | { |
|
|
129 | hv_delete (obj_cache, HeKEY (he), HeKLEN (he), G_DISCARD); |
|
|
130 | todo++; |
|
|
131 | } |
|
|
132 | } |
|
|
133 | else |
|
|
134 | break; |
|
|
135 | } |
|
|
136 | while (--todo); |
|
|
137 | } |
|
|
138 | |
|
|
139 | static SV * |
104 | static SV * |
140 | newSVptr (void *ptr, const char *klass) |
105 | newSVptr (void *ptr, const char *klass) |
141 | { |
106 | { |
142 | SV *sv; |
107 | SV *sv; |
143 | |
108 | |
… | |
… | |
145 | return &PL_sv_undef; |
110 | return &PL_sv_undef; |
146 | |
111 | |
147 | sv = (SV *)newHV (); |
112 | sv = (SV *)newHV (); |
148 | sv_magic (sv, 0, PERL_MAGIC_ext, (char *)ptr, 0); |
113 | sv_magic (sv, 0, PERL_MAGIC_ext, (char *)ptr, 0); |
149 | return sv_bless (newRV_noinc (sv), gv_stashpv (klass, 1)); |
114 | return sv_bless (newRV_noinc (sv), gv_stashpv (klass, 1)); |
|
|
115 | } |
|
|
116 | |
|
|
117 | template<class extendable> |
|
|
118 | SV * |
|
|
119 | newSVextendable (extendable *obj, const char *klass) |
|
|
120 | { |
|
|
121 | if (!obj) |
|
|
122 | return &PL_sv_undef; |
|
|
123 | |
|
|
124 | if (!obj->self) |
|
|
125 | obj->self = newSVptr (obj, klass); |
|
|
126 | |
|
|
127 | return newSVsv (static_cast<SV *>(obj->self)); |
150 | } |
128 | } |
151 | |
129 | |
152 | static void |
130 | static void |
153 | SVptr_cache_set (void *ptr, SV *sv) |
131 | SVptr_cache_set (void *ptr, SV *sv) |
154 | { |
132 | { |
… | |
… | |
266 | break; |
244 | break; |
267 | |
245 | |
268 | case DT_OBJECT: |
246 | case DT_OBJECT: |
269 | { |
247 | { |
270 | object *obj = va_arg (ap, object *); |
248 | object *obj = va_arg (ap, object *); |
271 | |
249 | sv = newSVextendable (obj, obj->type == PLAYER ? "cf::object::player::wrap" : "cf::object::wrap"); |
272 | if (!obj) |
|
|
273 | sv = &PL_sv_undef; |
|
|
274 | else |
|
|
275 | { |
|
|
276 | if (!obj->self) |
|
|
277 | switch (obj->type) |
|
|
278 | { |
|
|
279 | case MAP: |
|
|
280 | obj->self = static_cast<void *>(newSVptr (obj, "cf::object::map::wrap")); |
|
|
281 | break; |
|
|
282 | |
|
|
283 | case PLAYER: |
|
|
284 | obj->self = static_cast<void *>(newSVptr (obj, "cf::object::player::wrap")); |
|
|
285 | break; |
|
|
286 | |
|
|
287 | default: |
|
|
288 | obj->self = static_cast<void *>(newSVptr (obj, "cf::object::wrap")); |
|
|
289 | break; |
|
|
290 | } |
|
|
291 | |
|
|
292 | sv = newSVsv (static_cast<SV *>(obj->self)); |
|
|
293 | } |
|
|
294 | } |
250 | } |
295 | break; |
251 | break; |
296 | |
252 | |
297 | case DT_MAP: |
253 | case DT_MAP: |
|
|
254 | // va_arg (object *) when void * is passed is an XSI extension |
298 | sv = newSVptr (va_arg (ap, mapstruct *), "cf::map::wrap"); |
255 | sv = newSVextendable (va_arg (ap, mapstruct *), "cf::map::wrap"); |
299 | break; |
256 | break; |
300 | |
257 | |
301 | case DT_PLAYER: |
258 | case DT_PLAYER: |
302 | sv = newSVptr (va_arg (ap, player *), "cf::player::wrap"); |
259 | sv = newSVextendable (va_arg (ap, player *), "cf::player::wrap"); |
303 | break; |
260 | break; |
304 | |
261 | |
305 | case DT_ARCH: |
262 | case DT_ARCH: |
306 | sv = newSVptr (va_arg (ap, archetype *), "cf::arch::wrap"); |
263 | sv = newSVptr (va_arg (ap, archetype *), "cf::arch::wrap"); |
307 | break; |
264 | break; |
… | |
… | |
359 | } |
316 | } |
360 | |
317 | |
361 | va_end (ap); |
318 | va_end (ap); |
362 | |
319 | |
363 | return sv; |
320 | return sv; |
|
|
321 | } |
|
|
322 | |
|
|
323 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
324 | |
|
|
325 | void extendable_base::clear () |
|
|
326 | { |
|
|
327 | //if (self) fprintf (stderr, "free_ob_self %p\n", this);//D |
|
|
328 | if (self) SvREFCNT_dec (self), self = 0; |
|
|
329 | if (cb) SvREFCNT_dec (cb), cb = 0; |
|
|
330 | } |
|
|
331 | |
|
|
332 | void extendable_base::optimise () |
|
|
333 | { |
|
|
334 | // optional, and not used yet anyways |
|
|
335 | // // empty and unreferenced? nuke it |
|
|
336 | // if (SvREFCNT (sv) == 1 && SvREFCNT (SvRV (sv)) == 1 && !HvFILL ((HV *)(SvRV (sv)))) |
|
|
337 | // { |
|
|
338 | // hv_delete (obj_cache, HeKEY (he), HeKLEN (he), G_DISCARD); |
|
|
339 | // todo++; |
|
|
340 | // } |
|
|
341 | |
|
|
342 | } |
|
|
343 | |
|
|
344 | void extendable_base::reattach (data_type type, void *self) |
|
|
345 | { |
|
|
346 | dSP; |
|
|
347 | |
|
|
348 | ENTER; |
|
|
349 | SAVETMPS; |
|
|
350 | PUSHMARK (SP); |
|
|
351 | EXTEND (SP, 1); |
|
|
352 | PUSHs (sv_2mortal (newSVdt (type, self))); |
|
|
353 | PUTBACK; |
|
|
354 | call_pv ("cf::reattach", G_DISCARD | G_VOID | G_EVAL); |
|
|
355 | FREETMPS; |
|
|
356 | LEAVE; |
|
|
357 | } |
|
|
358 | |
|
|
359 | void extendable_base::instantiate (data_type type, void *self) |
|
|
360 | { |
|
|
361 | dSP; |
|
|
362 | |
|
|
363 | ENTER; |
|
|
364 | SAVETMPS; |
|
|
365 | PUSHMARK (SP); |
|
|
366 | EXTEND (SP, 1); |
|
|
367 | PUSHs (sv_2mortal (newSVdt (type, self))); |
|
|
368 | PUTBACK; |
|
|
369 | call_pv ("cf::instantiate", G_DISCARD | G_VOID | G_EVAL); |
|
|
370 | FREETMPS; |
|
|
371 | LEAVE; |
|
|
372 | } |
|
|
373 | |
|
|
374 | void extendable_base::clone (data_type type, void *self, void *dest) |
|
|
375 | { |
|
|
376 | dSP; |
|
|
377 | |
|
|
378 | ENTER; |
|
|
379 | SAVETMPS; |
|
|
380 | PUSHMARK (SP); |
|
|
381 | EXTEND (SP, 1); |
|
|
382 | PUSHs (sv_2mortal (newSVdt (type, self))); |
|
|
383 | PUSHs (sv_2mortal (newSVdt (type, dest))); |
|
|
384 | PUTBACK; |
|
|
385 | call_pv ("cf::clone", G_DISCARD | G_VOID | G_EVAL); |
|
|
386 | FREETMPS; |
|
|
387 | LEAVE; |
364 | } |
388 | } |
365 | |
389 | |
366 | ///////////////////////////////////////////////////////////////////////////// |
390 | ///////////////////////////////////////////////////////////////////////////// |
367 | |
391 | |
368 | extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr) |
392 | extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr) |
… | |
… | |
469 | object_insert = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_object_insert"); |
493 | object_insert = (void* (*)(int*, ...)) gethook (&rtype, hooktype, "cfapi_object_insert"); |
470 | |
494 | |
471 | cf_init_plugin (gethook); |
495 | cf_init_plugin (gethook); |
472 | |
496 | |
473 | /* Pick the global events you want to monitor from this plugin */ |
497 | /* Pick the global events you want to monitor from this plugin */ |
474 | registerGlobalEvent (NULL, EVENT_CLOCK, PLUGIN_NAME, globalEventListener); |
|
|
475 | //registerGlobalEvent (NULL, EVENT_CRASH, PLUGIN_NAME, globalEventListener); |
|
|
476 | registerGlobalEvent (NULL, EVENT_FIND_UNARMED_SKILL, PLUGIN_NAME, globalEventListener); |
|
|
477 | registerGlobalEvent (NULL, EVENT_SHOUT, PLUGIN_NAME, globalEventListener); |
498 | registerGlobalEvent (NULL, EVENT_SHOUT, PLUGIN_NAME, globalEventListener); |
478 | registerGlobalEvent (NULL, EVENT_TELL, PLUGIN_NAME, globalEventListener); |
499 | registerGlobalEvent (NULL, EVENT_TELL, PLUGIN_NAME, globalEventListener); |
479 | registerGlobalEvent (NULL, EVENT_MUZZLE, PLUGIN_NAME, globalEventListener); |
500 | registerGlobalEvent (NULL, EVENT_MUZZLE, PLUGIN_NAME, globalEventListener); |
480 | registerGlobalEvent (NULL, EVENT_KICK, PLUGIN_NAME, globalEventListener); |
501 | registerGlobalEvent (NULL, EVENT_KICK, PLUGIN_NAME, globalEventListener); |
481 | |
502 | |
… | |
… | |
493 | return NULL; |
514 | return NULL; |
494 | |
515 | |
495 | va_start (args, type); |
516 | va_start (args, type); |
496 | event_code = va_arg (args, int); |
517 | event_code = va_arg (args, int); |
497 | |
518 | |
498 | if (event_code == EVENT_CLOCK) |
519 | dSP; |
|
|
520 | |
|
|
521 | ENTER; |
|
|
522 | SAVETMPS; |
|
|
523 | |
|
|
524 | PUSHMARK (SP); |
|
|
525 | |
|
|
526 | EXTEND (SP, 10); |
|
|
527 | PUSHs (sv_2mortal (newSViv (event_code))); |
|
|
528 | |
|
|
529 | switch (event_code) |
499 | { |
530 | { |
500 | clean_obj_cache (); |
531 | case EVENT_CRASH: |
|
|
532 | break; |
|
|
533 | |
|
|
534 | case EVENT_SHOUT: |
|
|
535 | case EVENT_MUZZLE: |
|
|
536 | case EVENT_KICK: |
|
|
537 | PUSH_OB; |
|
|
538 | PUSH_PV; |
|
|
539 | break; |
|
|
540 | |
|
|
541 | case EVENT_TELL: |
|
|
542 | break; |
501 | } |
543 | } |
502 | else |
|
|
503 | { |
|
|
504 | dSP; |
|
|
505 | |
544 | |
506 | ENTER; |
|
|
507 | SAVETMPS; |
|
|
508 | |
|
|
509 | PUSHMARK (SP); |
|
|
510 | |
|
|
511 | EXTEND (SP, 10); |
|
|
512 | PUSHs (sv_2mortal (newSViv (event_code))); |
|
|
513 | |
|
|
514 | switch (event_code) |
|
|
515 | { |
|
|
516 | case EVENT_CRASH: |
|
|
517 | break; |
|
|
518 | |
|
|
519 | case EVENT_SHOUT: |
|
|
520 | case EVENT_MUZZLE: |
|
|
521 | case EVENT_KICK: |
|
|
522 | PUSH_OB; |
|
|
523 | PUSH_PV; |
|
|
524 | break; |
|
|
525 | |
|
|
526 | case EVENT_FIND_UNARMED_SKILL: |
|
|
527 | PUSH_OB; |
|
|
528 | break; |
|
|
529 | |
|
|
530 | case EVENT_TELL: |
|
|
531 | break; |
|
|
532 | } |
|
|
533 | |
|
|
534 | va_end (args); |
545 | va_end (args); |
535 | |
546 | |
536 | PUTBACK; |
547 | PUTBACK; |
537 | int count = call_pv ("cf::inject_global_event", G_SCALAR | G_EVAL); |
548 | int count = call_pv ("cf::inject_global_event", G_SCALAR | G_EVAL); |
538 | SPAGAIN; |
549 | SPAGAIN; |
539 | |
550 | |
540 | if (SvTRUE (ERRSV)) |
551 | if (SvTRUE (ERRSV)) |
541 | LOG (llevError, "global event '%d' callback evaluation error: %s", event_code, SvPV_nolen (ERRSV)); |
552 | LOG (llevError, "global event '%d' callback evaluation error: %s", event_code, SvPV_nolen (ERRSV)); |
542 | |
553 | |
543 | rv = count > 0 ? POPi : 0; |
554 | rv = count > 0 ? POPi : 0; |
544 | |
555 | |
545 | PUTBACK; |
556 | PUTBACK; |
546 | FREETMPS; |
557 | FREETMPS; |
547 | LEAVE; |
558 | LEAVE; |
548 | } |
|
|
549 | |
559 | |
550 | return &rv; |
560 | return &rv; |
551 | } |
561 | } |
552 | |
562 | |
553 | extern "C" void *cfperl_eventListener (int *type, ...) |
563 | extern "C" void *cfperl_eventListener (int *type, ...) |
… | |
… | |
685 | dSP; |
695 | dSP; |
686 | |
696 | |
687 | PUSHMARK (SP); |
697 | PUSHMARK (SP); |
688 | PUTBACK; |
698 | PUTBACK; |
689 | call_pv ("cf::main", G_DISCARD | G_VOID); |
699 | call_pv ("cf::main", G_DISCARD | G_VOID); |
690 | } |
|
|
691 | |
|
|
692 | void cfperl_free_ob (object *op) |
|
|
693 | { |
|
|
694 | if (op->self) fprintf (stderr, "free_ob_self %p %s\n", op, op->name);//D |
|
|
695 | if (op->self) SvREFCNT_dec (op->self), op->self = 0; |
|
|
696 | if (op->cb) SvREFCNT_dec (op->cb), op->cb = 0; |
|
|
697 | } |
700 | } |
698 | |
701 | |
699 | static event_klass klass_of[NUM_EVENT_TYPES] = { |
702 | static event_klass klass_of[NUM_EVENT_TYPES] = { |
700 | # define def(type,name) KLASS_ ## type, |
703 | # define def(type,name) KLASS_ ## type, |
701 | # include "eventinc.h" |
704 | # include "eventinc.h" |
… | |
… | |
1376 | const_event (TRIGGER) |
1379 | const_event (TRIGGER) |
1377 | const_event (CLOSE) |
1380 | const_event (CLOSE) |
1378 | const_event (TIMER) |
1381 | const_event (TIMER) |
1379 | const_event (MOVE) |
1382 | const_event (MOVE) |
1380 | |
1383 | |
1381 | //const_event (CLOCK) |
|
|
1382 | const_event (CRASH) |
|
|
1383 | const_event (SHOUT) |
1384 | const_event (SHOUT) |
1384 | const_event (TELL) |
1385 | const_event (TELL) |
1385 | const_event (MUZZLE) |
1386 | const_event (MUZZLE) |
1386 | const_event (KICK) |
1387 | const_event (KICK) |
1387 | const_event (FIND_UNARMED_SKILL) |
|
|
1388 | //const_event (FREE_OB) |
|
|
1389 | }; |
1388 | }; |
1390 | |
1389 | |
1391 | av = get_av ("cf::PLUGIN_EVENT", 1); |
1390 | av = get_av ("cf::PLUGIN_EVENT", 1); |
1392 | |
1391 | |
1393 | for (event = event_list + sizeof (event_list) / sizeof (event_list [0]); event-- > event_list; ) |
1392 | for (event = event_list + sizeof (event_list) / sizeof (event_list [0]); event-- > event_list; ) |