ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.177
Committed: Wed Mar 14 00:04:59 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.176: +26 -9 lines
Log Message:
- rewrote smooth face handling, as a side-effect, smoothing seems to work
  again and smooth faces can be reloaded.
- the server now sends the full animation for an object the first time
  it is seen, this uses slightly more bandwidth initially, but avoids
  the flickering for objects change their face later.

File Contents

# Content
1 /*****************************************************************************/
2 /* CrossFire, A Multiplayer game for the X Window System */
3 /*****************************************************************************/
4
5 /*
6 * This code is placed under the GNU General Public Licence (GPL)
7 *
8 * Copyright (C) 2001-2005 by Chachkoff Yann
9 * Copyright (C) 2006,2007 by Marc Lehmann <cf@schmorp.de>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #define PLUGIN_NAME "perl"
27 #define PLUGIN_VERSION "cfperl 0.5"
28
29 #include <plugin_common.h>
30 #include <sounds.h>
31 #include <cstdarg>
32 #include <sproto.h>
33
34 #include "loader.h"
35 #include "cfperl.h"
36 #include "shstr.h"
37
38 #include <unistd.h>
39 #if _POSIX_MEMLOCK
40 # include <sys/mman.h>
41 #endif
42
43 #include <EXTERN.h>
44 #include <perl.h>
45 #include <XSUB.h>
46
47 #include "CoroAPI.h"
48 #include "perlxsi.c"
49
50 extern sint64 *levels; // the experience table
51
52 typedef object object_ornull;
53 typedef maptile maptile_ornull;
54
55 #if IVSIZE >= 8
56 typedef IV val64;
57 # define newSVval64 newSViv
58 # define SvVAL64 SvIV
59 #else
60 typedef double val64;
61 # define newSVval64 newSVnv
62 # define SvVAL64 SvNV
63 #endif
64
65 static f_plug_api gethook = cfapi_get_hooks;
66 static f_plug_api object_set_property = cfapi_object_set_property;
67 static f_plug_api object_insert = cfapi_object_insert;
68
69 static PerlInterpreter *perl;
70
71 double runtime;
72
73 global gbl_ev;
74 static AV *cb_global, *cb_attachable, *cb_object, *cb_player, *cb_client, *cb_type, *cb_map;
75 static SV *sv_runtime;
76
77 static HV
78 *stash_cf,
79 *stash_cf_object_wrap,
80 *stash_cf_object_player_wrap,
81 *stash_cf_player_wrap,
82 *stash_cf_map_wrap,
83 *stash_cf_client_wrap,
84 *stash_cf_arch_wrap,
85 *stash_cf_party_wrap,
86 *stash_cf_region_wrap,
87 *stash_cf_living_wrap;
88
89 // helper cast function, returns super class * or 0
90 template<class super>
91 static super *
92 is_a (attachable *at)
93 {
94 //return dynamic_cast<super *>(at); // slower, safer
95 if (typeid (*at) == typeid (super))
96 return static_cast<super *>(at);
97 else
98 return 0;
99 }
100
101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
102
103 unordered_vector<attachable *> attachable::mortals;
104
105 attachable::~attachable ()
106 {
107 flags |=0x3300;//D
108 assert (!self);
109 assert (!cb);
110 }
111
112 int
113 attachable::refcnt_cnt () const
114 {
115 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
116 }
117
118 void
119 attachable::sever_self ()
120 {
121 if (HV *self = this->self)
122 {
123 // keep a refcount because sv_unmagic might call attachable_free,
124 // which might clear self, causing sv_unmagic to crash on a now
125 // invalid object.
126 SvREFCNT_inc (self);
127 hv_clear (self);
128 sv_unmagic ((SV *)self, PERL_MAGIC_ext);
129 SvREFCNT_dec (self);
130
131 // self *must* be null now because thats sv_unmagic's job.
132 assert (!this->self);
133 flags |= 0x80; // severed //D
134 }
135 }
136
137 void
138 attachable::optimise ()
139 {
140 if (self
141 && SvREFCNT (self) == 1
142 && !HvTOTALKEYS (self))
143 flags |= 0x40,//D
144 sever_self ();
145 }
146
147 // check wether the object really is dead
148 void
149 attachable::do_check ()
150 {
151 if (refcnt_cnt () > 0)
152 return;
153
154 destroy ();
155 }
156
157 void
158 attachable::do_destroy ()
159 {
160 invoke (EVENT_ATTACHABLE_DESTROY, DT_END);
161
162 if (cb)
163 {
164 SvREFCNT_dec (cb);
165 cb = 0;
166 }
167
168 if (self)
169 sever_self ();
170
171 flags |= 0x20; //D
172 mortals.push_back (this);
173 }
174
175 void
176 attachable::destroy ()
177 {
178 if (destroyed ())
179 return;
180
181 flags |= F_DESTROYED;
182 do_destroy ();
183 }
184
185 void
186 attachable::check_mortals ()
187 {
188 static int i = 0;
189
190 for (;;)
191 {
192 if (i >= mortals.size ())
193 {
194 i = 0;
195
196 if (mortals.size () > 1000)
197 fprintf (stderr, "mortal queue size (%d) exceeds 1000.\n", (int)mortals.size ());
198
199 break;
200 }
201
202 attachable *obj = mortals [i];
203
204 obj->refcnt_chk (); // unborrow from perl, if necessary
205
206 //if (obj->refcnt > 0 || obj->self)
207 if (obj->refcnt || obj->self)
208 {
209 //printf ("%p rc %d\n", obj, obj->refcnt_cnt ());//D
210 ++i; // further delay freeing
211
212 if (!(i & 0x3ff))
213 break;
214 }
215 else
216 {
217 mortals.erase (i);
218 delete obj;
219 }
220 }
221 }
222
223 attachable &
224 attachable::operator =(const attachable &src)
225 {
226 //if (self || cb)
227 //INVOKE_OBJECT (CLONE, this, ARG_OBJECT (dst));
228
229 attach = src.attach;
230 return *this;
231 }
232
233 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
234
235 static SV *
236 newSVptr (void *ptr, HV *stash, HV *hv = newHV ())
237 {
238 SV *sv;
239
240 if (!ptr)
241 return &PL_sv_undef;
242
243 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, 0, (char *)ptr, 0);
244 return sv_bless (newRV_noinc ((SV *)hv), stash);
245 }
246
247 static int
248 attachable_free (pTHX_ SV *sv, MAGIC *mg)
249 {
250 attachable *at = (attachable *)mg->mg_ptr;
251
252 //TODO: check if transaction behaviour is really required here
253 if (SV *self = (SV *)at->self)
254 {
255 at->self = 0;
256 SvREFCNT_dec (self);
257 }
258
259 // next line makes sense, but most objects still have refcnt 0 by default
260 //at->refcnt_chk ();
261 return 0;
262 }
263
264 MGVTBL attachable::vtbl = {0, 0, 0, 0, attachable_free};
265
266 static SV *
267 newSVattachable (attachable *obj, HV *stash)
268 {
269 if (!obj)
270 return &PL_sv_undef;
271
272 if (!obj->self)
273 {
274 obj->self = newHV ();
275 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
276 obj->flags |= (obj->flags & 0xc0) << 8;
277 obj->flags &= ~0xc0;//D
278 obj->flags |= 0x10;//D
279
280 // now bless the object _once_
281 return sv_bless (newRV_inc ((SV *)obj->self), stash);
282 }
283 else
284 {
285 SV *sv = newRV_inc ((SV *)obj->self);
286
287 if (Gv_AMG (stash)) // handle overload correctly, as the perl core does not
288 SvAMAGIC_on (sv);
289
290 return sv;
291 }
292 }
293
294 static void
295 clearSVptr (SV *sv)
296 {
297 if (SvROK (sv))
298 sv = SvRV (sv);
299
300 hv_clear ((HV *)sv);
301 sv_unmagic (sv, PERL_MAGIC_ext);
302 }
303
304 static long
305 SvPTR (SV *sv, const char *klass)
306 {
307 if (!sv_derived_from (sv, klass))
308 croak ("object of type %s expected", klass);
309
310 MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
311
312 if (!mg)
313 croak ("perl code used %s object, but C object is already destroyed, caught", klass);
314
315 return (long)mg->mg_ptr;
316 }
317
318 static long
319 SvPTR_ornull (SV *sv, const char *klass)
320 {
321 if (SvOK (sv))
322 return SvPTR (sv, klass);
323 else
324 return 0;
325 }
326
327 inline SV *to_sv (const shstr & v) { return v ? newSVpvn ((const char *)v, v.length ()) : &PL_sv_undef; }
328 inline SV *to_sv (const char * v) { return newSVpv (v, 0); }
329 inline SV *to_sv (bool v) { return newSViv (v); }
330 inline SV *to_sv ( signed char v) { return newSViv (v); }
331 inline SV *to_sv (unsigned char v) { return newSViv (v); }
332 inline SV *to_sv ( signed short v) { return newSViv (v); }
333 inline SV *to_sv (unsigned short v) { return newSVuv (v); }
334 inline SV *to_sv ( signed int v) { return newSViv (v); }
335 inline SV *to_sv (unsigned int v) { return newSVuv (v); }
336 inline SV *to_sv ( signed long v) { return newSViv (v); }
337 inline SV *to_sv (unsigned long v) { return newSVuv (v); }
338 inline SV *to_sv ( signed long long v) { return newSVval64 (v); }
339 inline SV *to_sv (unsigned long long v) { return newSVval64 (v); }
340 inline SV *to_sv (float v) { return newSVnv (v); }
341 inline SV *to_sv (double v) { return newSVnv (v); }
342 inline SV *to_sv (client * v) { return newSVattachable (v, stash_cf_client_wrap); }
343 inline SV *to_sv (player * v) { return newSVattachable (v, stash_cf_player_wrap); }
344 inline SV *to_sv (object * v) { return newSVattachable (v, v && v->type == PLAYER ? stash_cf_object_player_wrap : stash_cf_object_wrap); }
345 inline SV *to_sv (maptile * v) { return newSVattachable (v, stash_cf_map_wrap); }
346 inline SV *to_sv (archetype * v) { return newSVattachable (v, stash_cf_arch_wrap); }
347 inline SV *to_sv (partylist * v) { return newSVptr (v, stash_cf_party_wrap); }
348 inline SV *to_sv (region * v) { return newSVptr (v, stash_cf_region_wrap); }
349 inline SV *to_sv (living * v) { return newSVptr (v, stash_cf_living_wrap); }
350
351 inline SV *to_sv (object & v) { return to_sv (&v); }
352 inline SV *to_sv (living & v) { return to_sv (&v); }
353
354 //inline SV *to_sv (faceinfo * v) { return to_sv (v->name); }
355 inline SV *to_sv (treasurelist * v) { return to_sv (v->name); }
356 inline SV *to_sv (std::string & v) { return newSVpvn (v.data (), v.size ()); }
357
358 inline SV *to_sv (UUID v)
359 {
360 char buf[128];
361 snprintf (buf, 128, "<1.%" PRIx64 ">", v.seq);
362 return newSVpv (buf, 0);
363 }
364
365 inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPV_nolen (sv) : 0; }
366 inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; }
367 inline void sv_to (SV *sv, bool &v) { v = SvIV (sv); }
368 inline void sv_to (SV *sv, signed char &v) { v = SvIV (sv); }
369 inline void sv_to (SV *sv, unsigned char &v) { v = SvIV (sv); }
370 inline void sv_to (SV *sv, signed short &v) { v = SvIV (sv); }
371 inline void sv_to (SV *sv, unsigned short &v) { v = SvIV (sv); }
372 inline void sv_to (SV *sv, signed int &v) { v = SvIV (sv); }
373 inline void sv_to (SV *sv, unsigned int &v) { v = SvUV (sv); }
374 inline void sv_to (SV *sv, signed long &v) { v = SvIV (sv); }
375 inline void sv_to (SV *sv, unsigned long &v) { v = SvUV (sv); }
376 inline void sv_to (SV *sv, signed long long &v) { v = ( signed long long)SvVAL64 (sv); }
377 inline void sv_to (SV *sv, unsigned long long &v) { v = (unsigned long long)SvVAL64 (sv); }
378 inline void sv_to (SV *sv, float &v) { v = SvNV (sv); }
379 inline void sv_to (SV *sv, double &v) { v = SvNV (sv); }
380 inline void sv_to (SV *sv, client * &v) { v = (client *)(attachable *)SvPTR_ornull (sv, "cf::client"); }
381 inline void sv_to (SV *sv, player * &v) { v = (player *)(attachable *)SvPTR_ornull (sv, "cf::player"); }
382 inline void sv_to (SV *sv, object * &v) { v = (object *)(attachable *)SvPTR_ornull (sv, "cf::object"); }
383 inline void sv_to (SV *sv, archetype * &v) { v = (archetype *)(attachable *)SvPTR_ornull (sv, "cf::arch"); }
384 inline void sv_to (SV *sv, maptile * &v) { v = (maptile *)(attachable *)SvPTR_ornull (sv, "cf::map"); }
385 inline void sv_to (SV *sv, attachable * &v) { v = (attachable *)SvPTR_ornull (sv, "cf::attachable"); }
386 inline void sv_to (SV *sv, partylist * &v) { v = (partylist *)SvPTR_ornull (sv, "cf::party"); }
387 inline void sv_to (SV *sv, region * &v) { v = (region *)SvPTR_ornull (sv, "cf::region"); }
388 inline void sv_to (SV *sv, living * &v) { v = (living *)SvPTR_ornull (sv, "cf::living"); }
389
390 //inline void sv_to (SV *sv, faceinfo * &v) { v = &faces [face_find (SvPV_nolen (sv), 0)]; }
391 inline void sv_to (SV *sv, treasurelist * &v) { v = find_treasurelist (SvPV_nolen (sv)); }
392
393 template<class T>
394 inline void sv_to (SV *sv, refptr<T> &v) { T *tmp; sv_to (sv, tmp); v = tmp; }
395
396 template<int N>
397 inline void sv_to (SV *sv, char (&v)[N]) { assign (v, SvPV_nolen (sv)); }
398
399 inline void sv_to (SV *sv, rangetype &v) { v = (rangetype) SvIV (sv); }
400 inline void sv_to (SV *sv, bowtype_t &v) { v = (bowtype_t) SvIV (sv); }
401 inline void sv_to (SV *sv, petmode_t &v) { v = (petmode_t) SvIV (sv); }
402 inline void sv_to (SV *sv, usekeytype &v) { v = (usekeytype) SvIV (sv); }
403 inline void sv_to (SV *sv, unapplymode &v) { v = (unapplymode) SvIV (sv); }
404
405 inline void sv_to (SV *sv, std::string &v)
406 {
407 STRLEN len;
408 char *data = SvPVbyte (sv, len);
409 v.assign (data, len);
410 }
411
412 inline void sv_to (SV *sv, UUID &v)
413 {
414 unsigned int version;
415
416 if (2 != sscanf (SvPV_nolen (sv), "<%d.%" SCNx64 ">", &version, &v.seq) || 1 != version)
417 croak ("unparsable uuid: %s", SvPV_nolen (sv));
418 }
419
420 inline void sv_to (SV *sv, object::flags_t::reference v) { v = SvTRUE (sv); }
421
422 static SV *
423 newSVdt_va (va_list &ap, data_type type)
424 {
425 SV *sv;
426
427 switch (type)
428 {
429 case DT_INT:
430 sv = newSViv (va_arg (ap, int));
431 break;
432
433 case DT_INT64:
434 sv = newSVval64 ((val64)va_arg (ap, sint64));
435 break;
436
437 case DT_DOUBLE:
438 sv = newSVnv (va_arg (ap, double));
439 break;
440
441 case DT_STRING:
442 {
443 char *str = (char *)va_arg (ap, const char *);
444 sv = str ? newSVpv (str, 0) : &PL_sv_undef;
445 }
446 break;
447
448 case DT_DATA:
449 {
450 char *str = (char *)va_arg (ap, const void *);
451 int len = va_arg (ap, int);
452 sv = str ? newSVpv (str, len) : &PL_sv_undef;
453 }
454 break;
455
456 case DT_OBJECT:
457 sv = to_sv (va_arg (ap, object *));
458 break;
459
460 case DT_MAP:
461 // va_arg (object *) when void * is passed is an XSI extension
462 sv = to_sv (va_arg (ap, maptile *));
463 break;
464
465 case DT_CLIENT:
466 sv = to_sv (va_arg (ap, client *));
467 break;
468
469 case DT_PLAYER:
470 sv = to_sv (va_arg (ap, player *));
471 break;
472
473 case DT_ARCH:
474 sv = to_sv (va_arg (ap, archetype *));
475 break;
476
477 case DT_PARTY:
478 sv = to_sv (va_arg (ap, partylist *));
479 break;
480
481 case DT_REGION:
482 sv = to_sv (va_arg (ap, region *));
483 break;
484
485 default:
486 assert (("unhandled type in newSVdt_va", 0));
487 }
488
489 return sv;
490 }
491
492 static SV *
493 newSVdt (data_type type, ...)
494 {
495 va_list ap;
496
497 va_start (ap, type);
498 SV *sv = newSVdt_va (ap, type);
499 va_end (ap);
500
501 return sv;
502 }
503
504 static SV *
505 newSVcfapi (int type, ...)
506 {
507 SV *sv;
508
509 va_list ap;
510 va_start (ap, type);
511
512 switch (type)
513 {
514 case CFAPI_INT: sv = newSViv (*va_arg (ap, int * )); break;
515 case CFAPI_LONG: sv = newSVval64 (*va_arg (ap, sint64 *)); break;
516 case CFAPI_DOUBLE: sv = newSVnv (*va_arg (ap, double *)); break;
517 case CFAPI_STRING: sv = newSVdt_va (ap, DT_STRING); break;
518 case CFAPI_POBJECT: sv = newSVdt_va (ap, DT_OBJECT); break;
519 case CFAPI_PMAP: sv = newSVdt_va (ap, DT_MAP ); break;
520 case CFAPI_PPLAYER: sv = newSVdt_va (ap, DT_PLAYER); break;
521 case CFAPI_PARCH: sv = newSVdt_va (ap, DT_ARCH ); break;
522 case CFAPI_PPARTY: sv = newSVdt_va (ap, DT_PARTY ); break;
523 case CFAPI_PREGION: sv = newSVdt_va (ap, DT_REGION); break;
524
525 default:
526 assert (("unhandled type in newSVcfapi", 0));
527 }
528
529 va_end (ap);
530
531 return sv;
532 }
533
534 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
535
536 SV *
537 registry (attachable *ext)
538 {
539 if (!ext->cb)
540 ext->cb = newAV ();
541
542 return newRV_inc ((SV *)ext->cb);
543 }
544
545 /////////////////////////////////////////////////////////////////////////////
546
547 extern "C" int cfperl_initPlugin (const char *iversion, f_plug_api gethooksptr)
548 {
549 return 0;
550 }
551
552 static CommArray_s rtn_cmd;
553
554 static int
555 runPluginCommand (object *obj, char *params)
556 {
557 return -1;
558 }
559
560 extern "C" void *cfperl_getPluginProperty (int *type, ...)
561 {
562 va_list args;
563 char *propname;
564 int i;
565 va_start (args, type);
566 propname = va_arg (args, char *);
567 //printf ("Property name: %s\n", propname);
568
569 if (!strcmp (propname, "command?"))
570 return NULL;
571 else if (!strcmp (propname, "Identification"))
572 {
573 va_end (args);
574 return (void *)PLUGIN_NAME;
575 }
576 else if (!strcmp (propname, "FullName"))
577 {
578 va_end (args);
579 return (void *)PLUGIN_VERSION;
580 }
581 else
582 va_end (args);
583
584 return NULL;
585 }
586
587 extern "C" int cfperl_postInitPlugin ()
588 {
589 int hooktype = 1;
590 int rtype = 0;
591
592 cf_init_plugin (gethook);
593
594 return 0;
595 }
596
597 extern "C" int cfperl_closePlugin ()
598 {
599 return 0;
600 }
601
602 void
603 cfperl_init ()
604 {
605 PERL_SYS_INIT3 (&settings.argc, &settings.argv, 0);
606 perl = perl_alloc ();
607 perl_construct (perl);
608
609 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
610
611 char *argv[] = {
612 "",
613 "-e"
614 "use Event; use Coro;" // required for bootstrap
615 "cf->bootstrap;" // required for datadir :*>
616 "unshift @INC, cf::datadir ();"
617 "require cf;"
618 };
619
620 if (perl_parse (perl, xs_init, 2, argv, (char **)NULL) || perl_run (perl))
621 {
622 printf ("unable to initialize perl-interpreter, aborting.\n");
623 exit (EXIT_FAILURE);
624 }
625
626 {
627 dSP;
628
629 PUSHMARK (SP);
630 PUTBACK;
631 call_pv ("cf::init", G_DISCARD | G_VOID);
632 }
633 }
634
635 void cfperl_main ()
636 {
637 dSP;
638
639 PUSHMARK (SP);
640 PUTBACK;
641 call_pv ("cf::main", G_DISCARD | G_VOID);
642 }
643
644 void
645 attachable::instantiate ()
646 {
647 if (attach)
648 {
649 invoke (EVENT_ATTACHABLE_INSTANTIATE, ARG_STRING (attach), DT_END);
650 attach = 0;
651 }
652 }
653
654 void
655 attachable::reattach ()
656 {
657 optimise ();
658 //TODO: check for _attachment's, very important for restarts
659 invoke (EVENT_ATTACHABLE_REATTACH, DT_END);
660 }
661
662 static event_klass klass_of[NUM_EVENT_TYPES] = {
663 # define def(type,name) KLASS_ ## type,
664 # include "eventinc.h"
665 # undef def
666 };
667
668 #define KLASS_OF(event) (((unsigned int)event) < NUM_EVENT_TYPES ? klass_of [event] : KLASS_NONE)
669
670 static void
671 gather_callbacks (AV *&callbacks, AV *registry, event_type event)
672 {
673 // event must be in array
674 if (event >= 0 && event <= AvFILLp (registry))
675 {
676 SV *cbs_ = AvARRAY (registry)[event];
677
678 // element must be list of callback entries
679 if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
680 {
681 AV *cbs = (AV *)SvRV (cbs_);
682
683 // no callback entries, no callbacks to call
684 if (AvFILLp (cbs) >= 0)
685 {
686 if (!callbacks)
687 {
688 callbacks = newAV ();
689 av_extend (callbacks, 16);
690 }
691
692 // never use SvREFCNT_inc to copy values, but its ok here :)
693 for (int i = 0; i <= AvFILLp (cbs); ++i)
694 av_push (callbacks, SvREFCNT_inc (AvARRAY (cbs)[i]));
695 }
696 }
697 }
698 }
699
700 void
701 attachable::gather_callbacks (AV *&callbacks, event_type event) const
702 {
703 ::gather_callbacks (callbacks, cb_attachable, event);
704
705 if (cb)
706 ::gather_callbacks (callbacks, cb, event);
707 }
708
709 void
710 global::gather_callbacks (AV *&callbacks, event_type event) const
711 {
712 ::gather_callbacks (callbacks, cb_object, event);
713 }
714
715 void
716 object::gather_callbacks (AV *&callbacks, event_type event) const
717 {
718 if (subtype && type + subtype * NUM_SUBTYPES <= AvFILLp (cb_type))
719 {
720 SV *registry = AvARRAY (cb_type)[type + subtype * NUM_SUBTYPES];
721
722 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
723 ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
724 }
725
726 if (type <= AvFILLp (cb_type))
727 {
728 SV *registry = AvARRAY (cb_type)[type];
729
730 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
731 ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
732 }
733
734 attachable::gather_callbacks (callbacks, event);
735 ::gather_callbacks (callbacks, cb_object, event);
736 }
737
738 void
739 archetype::gather_callbacks (AV *&callbacks, event_type event) const
740 {
741 attachable::gather_callbacks (callbacks, event);
742 //TODO//::gather_callbacks (callbacks, cb_archetype, event);
743 }
744
745 void
746 client::gather_callbacks (AV *&callbacks, event_type event) const
747 {
748 attachable::gather_callbacks (callbacks, event);
749 ::gather_callbacks (callbacks, cb_client, event);
750 }
751
752 void
753 player::gather_callbacks (AV *&callbacks, event_type event) const
754 {
755 attachable::gather_callbacks (callbacks, event);
756 ::gather_callbacks (callbacks, cb_player, event);
757 }
758
759 void
760 maptile::gather_callbacks (AV *&callbacks, event_type event) const
761 {
762 attachable::gather_callbacks (callbacks, event);
763 ::gather_callbacks (callbacks, cb_map, event);
764 }
765
766 bool
767 attachable::invoke (event_type event, ...)
768 {
769 data_type dt;
770 va_list ap;
771
772 va_start (ap, event);
773
774 // callback call ordering should be:
775 // 1. per-object callback
776 // 2. per-class object
777 // 3. per-type callback
778 // 4. global callbacks
779
780 AV *callbacks = 0;
781 gather_callbacks (callbacks, event);
782
783 // short-circuit processing if no callbacks found/defined
784 if (!callbacks)
785 return 0;
786
787 CALL_BEGIN (3);
788 CALL_ARG_SV (newSViv (event)); // only used for debugging nowadays
789 CALL_ARG_SV (newRV_noinc ((SV *)callbacks));
790
791 //TODO: unhack
792 if (object *op = is_a<object>(this)) CALL_ARG_SV (newSVdt (DT_OBJECT, op));
793 else if (player *pl = is_a<player>(this)) CALL_ARG_SV (newSVdt (DT_PLAYER, pl));
794 else if (client *ns = is_a<client>(this)) CALL_ARG_SV (newSVdt (DT_CLIENT, ns));
795 else if (maptile *m = is_a<maptile>(this)) CALL_ARG_SV (newSVdt (DT_MAP, m));
796 else if (global *gl = is_a<global>(this)) /*nop*/;
797 else
798 abort (); //TODO
799
800 for (;;)
801 {
802 dt = (data_type) va_arg (ap, int);
803
804 if (dt == DT_END)
805 break;
806 else if (dt == DT_AV)
807 {
808 AV *av = va_arg (ap, AV *);
809
810 for (int i = 0; i <= av_len (av); ++i)
811 XPUSHs (*av_fetch (av, i, 1));
812 }
813 else
814 XPUSHs (sv_2mortal (newSVdt_va (ap, dt)));
815 }
816
817 va_end (ap);
818
819 CALL_CALL ("cf::do_invoke", G_SCALAR);
820 count = count > 0 ? POPi : 0;
821
822 CALL_END;
823
824 return count;
825 }
826
827 SV *
828 cfperl_result (int idx)
829 {
830 AV *av = get_av ("cfperl::invoke_results", 0);
831 if (!av)
832 return &PL_sv_undef;
833
834 SV **sv = av_fetch (av, idx, 0);
835 if (!sv)
836 return &PL_sv_undef;
837
838 return *sv;
839 }
840
841 int
842 cfperl_result_INT (int idx)
843 {
844 return SvIV (cfperl_result (idx));
845 }
846
847 double
848 cfperl_result_DOUBLE (int idx)
849 {
850 return SvNV (cfperl_result (idx));
851 }
852
853 /////////////////////////////////////////////////////////////////////////////
854
855 void
856 cfperl_emergency_save ()
857 {
858 CALL_BEGIN (0);
859 CALL_CALL ("cf::emergency_save", G_VOID);
860 CALL_END;
861 }
862
863 void
864 cfperl_cleanup (int make_core)
865 {
866 CALL_BEGIN (1);
867 CALL_ARG (make_core);
868 CALL_CALL ("cf::post_cleanup", G_VOID);
869 CALL_END;
870 }
871
872 maptile *
873 maptile::find_sync (const char *path, maptile *origin)
874 {
875 CALL_BEGIN (2);
876 CALL_ARG (path);
877 CALL_ARG (origin);
878 CALL_CALL ("cf::map::find_sync", G_SCALAR);
879
880 maptile *retval;
881
882 if (count)
883 sv_to (POPs, retval);
884 else
885 retval = 0;
886
887 CALL_END;
888
889 return retval;
890 }
891
892 maptile *
893 maptile::find_async (const char *path, maptile *origin)
894 {
895 CALL_BEGIN (2);
896 CALL_ARG (path);
897 CALL_ARG (origin);
898 CALL_CALL ("cf::map::find_async", G_SCALAR);
899
900 maptile *retval;
901
902 if (count)
903 sv_to (POPs, retval);
904 else
905 retval = 0;
906
907 CALL_END;
908
909 return retval;
910 }
911
912 void
913 maptile::do_load_sync ()
914 {
915 CALL_BEGIN (1);
916 CALL_ARG (this);
917 CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
918 CALL_END;
919 }
920
921 void
922 maptile::change_all_map_light (int change)
923 {
924 CALL_BEGIN (1);
925 CALL_ARG (change);
926 CALL_CALL ("cf::map::change_all_map_light", G_VOID);
927 CALL_END;
928 }
929
930 void
931 object::enter_exit (object *exit)
932 {
933 if (type != PLAYER)
934 return;
935
936 CALL_BEGIN (2);
937 CALL_ARG (this);
938 CALL_ARG (exit);
939 CALL_CALL ("cf::object::player::enter_exit", G_VOID);
940 CALL_END;
941 }
942
943 /////////////////////////////////////////////////////////////////////////////
944
945 struct EventAPI *watcher_base::GEventAPI;
946 struct CoroAPI *coroapi::GCoroAPI;
947
948 int coroapi::cede_counter;
949
950 static void iw_dispatch (pe_event *ev)
951 {
952 iw *w = (iw *)ev->ext_data;
953 w->call (*w);
954 }
955
956 void
957 iw::alloc ()
958 {
959 pe = GEventAPI->new_idle (0, 0);
960
961 WaREENTRANT_off (pe);
962 pe->base.callback = (void *)iw_dispatch;
963 pe->base.ext_data = (void *)this;
964 }
965
966 static void iow_dispatch (pe_event *ev)
967 {
968 iow *w = (iow *)ev->ext_data;
969 w->call (*w, ((pe_ioevent *)ev)->got);
970 }
971
972 void
973 iow::alloc ()
974 {
975 pe = GEventAPI->new_io (0, 0);
976
977 WaREENTRANT_off (pe);
978 pe->base.callback = (void *)iow_dispatch;
979 pe->base.ext_data = (void *)this;
980
981 pe->fd = -1;
982 pe->poll = 0;
983 }
984
985 void
986 iow::fd (int fd)
987 {
988 pe->fd = fd;
989 }
990
991 int
992 iow::poll ()
993 {
994 return pe->poll;
995 }
996
997 void
998 iow::poll (int events)
999 {
1000 if (pe->poll != events)
1001 {
1002 if (pe->poll) stop ();
1003 pe->poll = events;
1004 if (pe->poll) start ();
1005 }
1006 }
1007
1008 void
1009 _connect_to_perl ()
1010 {
1011 stash_cf = gv_stashpv ("cf" , 1);
1012
1013 stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1014 stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1015 stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1016 stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1017 stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1018 stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1019 stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1020 stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1021 stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1022
1023 sv_runtime = get_sv ("cf::RUNTIME", 1);
1024 sv_upgrade (sv_runtime, SVt_NV);
1025
1026 cb_global = get_av ("cf::CB_GLOBAL", 1);
1027 cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1028 cb_object = get_av ("cf::CB_OBJECT", 1);
1029 cb_player = get_av ("cf::CB_PLAYER", 1);
1030 cb_client = get_av ("cf::CB_CLIENT", 1);
1031 cb_type = get_av ("cf::CB_TYPE" , 1);
1032 cb_map = get_av ("cf::CB_MAP" , 1);
1033 }
1034
1035 MODULE = cf PACKAGE = cf PREFIX = cf_
1036
1037 BOOT:
1038 {
1039 _connect_to_perl ();
1040
1041 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1042 I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1043
1044 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1045
1046 static const struct {
1047 const char *name;
1048 IV iv;
1049 } *civ, const_iv[] = {
1050 # define const_iv(name) { # name, (IV)name },
1051 const_iv (llevError)
1052 const_iv (llevInfo)
1053 const_iv (llevDebug)
1054 const_iv (llevMonster)
1055
1056 const_iv (MAX_TIME)
1057 const_iv (PLAYER)
1058 const_iv (TRANSPORT)
1059 const_iv (ROD)
1060 const_iv (TREASURE)
1061 const_iv (POTION)
1062 const_iv (FOOD)
1063 const_iv (POISON)
1064 const_iv (BOOK)
1065 const_iv (CLOCK)
1066 const_iv (ARROW)
1067 const_iv (BOW)
1068 const_iv (WEAPON)
1069 const_iv (ARMOUR)
1070 const_iv (PEDESTAL)
1071 const_iv (ALTAR)
1072 const_iv (LOCKED_DOOR)
1073 const_iv (SPECIAL_KEY)
1074 const_iv (MAP)
1075 const_iv (DOOR)
1076 const_iv (KEY)
1077 const_iv (TIMED_GATE)
1078 const_iv (TRIGGER)
1079 const_iv (GRIMREAPER)
1080 const_iv (MAGIC_EAR)
1081 const_iv (TRIGGER_BUTTON)
1082 const_iv (TRIGGER_ALTAR)
1083 const_iv (TRIGGER_PEDESTAL)
1084 const_iv (SHIELD)
1085 const_iv (HELMET)
1086 const_iv (HORN)
1087 const_iv (MONEY)
1088 const_iv (CLASS)
1089 const_iv (GRAVESTONE)
1090 const_iv (AMULET)
1091 const_iv (PLAYERMOVER)
1092 const_iv (TELEPORTER)
1093 const_iv (CREATOR)
1094 const_iv (SKILL)
1095 const_iv (EARTHWALL)
1096 const_iv (GOLEM)
1097 const_iv (THROWN_OBJ)
1098 const_iv (BLINDNESS)
1099 const_iv (GOD)
1100 const_iv (DETECTOR)
1101 const_iv (TRIGGER_MARKER)
1102 const_iv (DEAD_OBJECT)
1103 const_iv (DRINK)
1104 const_iv (MARKER)
1105 const_iv (HOLY_ALTAR)
1106 const_iv (PLAYER_CHANGER)
1107 const_iv (BATTLEGROUND)
1108 const_iv (PEACEMAKER)
1109 const_iv (GEM)
1110 const_iv (FIREWALL)
1111 const_iv (ANVIL)
1112 const_iv (CHECK_INV)
1113 const_iv (MOOD_FLOOR)
1114 const_iv (EXIT)
1115 const_iv (ENCOUNTER)
1116 const_iv (SHOP_FLOOR)
1117 const_iv (SHOP_MAT)
1118 const_iv (RING)
1119 const_iv (FLOOR)
1120 const_iv (FLESH)
1121 const_iv (INORGANIC)
1122 const_iv (SKILL_TOOL)
1123 const_iv (LIGHTER)
1124 const_iv (BUILDABLE_WALL)
1125 const_iv (MISC_OBJECT)
1126 const_iv (LAMP)
1127 const_iv (DUPLICATOR)
1128 const_iv (SPELLBOOK)
1129 const_iv (CLOAK)
1130 const_iv (SPINNER)
1131 const_iv (GATE)
1132 const_iv (BUTTON)
1133 const_iv (CF_HANDLE)
1134 const_iv (HOLE)
1135 const_iv (TRAPDOOR)
1136 const_iv (SIGN)
1137 const_iv (BOOTS)
1138 const_iv (GLOVES)
1139 const_iv (SPELL)
1140 const_iv (SPELL_EFFECT)
1141 const_iv (CONVERTER)
1142 const_iv (BRACERS)
1143 const_iv (POISONING)
1144 const_iv (SAVEBED)
1145 const_iv (WAND)
1146 const_iv (SCROLL)
1147 const_iv (DIRECTOR)
1148 const_iv (GIRDLE)
1149 const_iv (FORCE)
1150 const_iv (POTION_EFFECT)
1151 const_iv (EVENT_CONNECTOR)
1152 const_iv (CLOSE_CON)
1153 const_iv (CONTAINER)
1154 const_iv (ARMOUR_IMPROVER)
1155 const_iv (WEAPON_IMPROVER)
1156 const_iv (SKILLSCROLL)
1157 const_iv (DEEP_SWAMP)
1158 const_iv (IDENTIFY_ALTAR)
1159 const_iv (MENU)
1160 const_iv (RUNE)
1161 const_iv (TRAP)
1162 const_iv (POWER_CRYSTAL)
1163 const_iv (CORPSE)
1164 const_iv (DISEASE)
1165 const_iv (SYMPTOM)
1166 const_iv (BUILDER)
1167 const_iv (MATERIAL)
1168 const_iv (ITEM_TRANSFORMER)
1169
1170 const_iv (NUM_SUBTYPES)
1171
1172 const_iv (ST_BD_BUILD)
1173 const_iv (ST_BD_REMOVE)
1174
1175 const_iv (ST_MAT_FLOOR)
1176 const_iv (ST_MAT_WALL)
1177 const_iv (ST_MAT_ITEM)
1178
1179 const_iv (AT_PHYSICAL)
1180 const_iv (AT_MAGIC)
1181 const_iv (AT_FIRE)
1182 const_iv (AT_ELECTRICITY)
1183 const_iv (AT_COLD)
1184 const_iv (AT_CONFUSION)
1185 const_iv (AT_ACID)
1186 const_iv (AT_DRAIN)
1187 const_iv (AT_WEAPONMAGIC)
1188 const_iv (AT_GHOSTHIT)
1189 const_iv (AT_POISON)
1190 const_iv (AT_SLOW)
1191 const_iv (AT_PARALYZE)
1192 const_iv (AT_TURN_UNDEAD)
1193 const_iv (AT_FEAR)
1194 const_iv (AT_CANCELLATION)
1195 const_iv (AT_DEPLETE)
1196 const_iv (AT_DEATH)
1197 const_iv (AT_CHAOS)
1198 const_iv (AT_COUNTERSPELL)
1199 const_iv (AT_GODPOWER)
1200 const_iv (AT_HOLYWORD)
1201 const_iv (AT_BLIND)
1202 const_iv (AT_INTERNAL)
1203 const_iv (AT_LIFE_STEALING)
1204 const_iv (AT_DISEASE)
1205
1206 const_iv (WEAP_HIT)
1207 const_iv (WEAP_SLASH)
1208 const_iv (WEAP_PIERCE)
1209 const_iv (WEAP_CLEAVE)
1210 const_iv (WEAP_SLICE)
1211 const_iv (WEAP_STAB)
1212 const_iv (WEAP_WHIP)
1213 const_iv (WEAP_CRUSH)
1214 const_iv (WEAP_BLUD)
1215
1216 const_iv (FLAG_ALIVE)
1217 const_iv (FLAG_WIZ)
1218 const_iv (FLAG_REMOVED)
1219 const_iv (FLAG_FREED)
1220 const_iv (FLAG_WAS_WIZ)
1221 const_iv (FLAG_APPLIED)
1222 const_iv (FLAG_UNPAID)
1223 const_iv (FLAG_USE_SHIELD)
1224 const_iv (FLAG_NO_PICK)
1225 const_iv (FLAG_ANIMATE)
1226 const_iv (FLAG_MONSTER)
1227 const_iv (FLAG_FRIENDLY)
1228 const_iv (FLAG_GENERATOR)
1229 const_iv (FLAG_IS_THROWN)
1230 const_iv (FLAG_AUTO_APPLY)
1231 const_iv (FLAG_PLAYER_SOLD)
1232 const_iv (FLAG_SEE_INVISIBLE)
1233 const_iv (FLAG_CAN_ROLL)
1234 const_iv (FLAG_OVERLAY_FLOOR)
1235 const_iv (FLAG_IS_TURNABLE)
1236 const_iv (FLAG_IS_USED_UP)
1237 const_iv (FLAG_IDENTIFIED)
1238 const_iv (FLAG_REFLECTING)
1239 const_iv (FLAG_CHANGING)
1240 const_iv (FLAG_SPLITTING)
1241 const_iv (FLAG_HITBACK)
1242 const_iv (FLAG_STARTEQUIP)
1243 const_iv (FLAG_BLOCKSVIEW)
1244 const_iv (FLAG_UNDEAD)
1245 const_iv (FLAG_SCARED)
1246 const_iv (FLAG_UNAGGRESSIVE)
1247 const_iv (FLAG_REFL_MISSILE)
1248 const_iv (FLAG_REFL_SPELL)
1249 const_iv (FLAG_NO_MAGIC)
1250 const_iv (FLAG_NO_FIX_PLAYER)
1251 const_iv (FLAG_IS_LIGHTABLE)
1252 const_iv (FLAG_TEAR_DOWN)
1253 const_iv (FLAG_RUN_AWAY)
1254 const_iv (FLAG_PICK_UP)
1255 const_iv (FLAG_UNIQUE)
1256 const_iv (FLAG_NO_DROP)
1257 const_iv (FLAG_WIZCAST)
1258 const_iv (FLAG_CAST_SPELL)
1259 const_iv (FLAG_USE_SCROLL)
1260 const_iv (FLAG_USE_RANGE)
1261 const_iv (FLAG_USE_BOW)
1262 const_iv (FLAG_USE_ARMOUR)
1263 const_iv (FLAG_USE_WEAPON)
1264 const_iv (FLAG_USE_RING)
1265 const_iv (FLAG_READY_RANGE)
1266 const_iv (FLAG_READY_BOW)
1267 const_iv (FLAG_XRAYS)
1268 const_iv (FLAG_NO_APPLY)
1269 const_iv (FLAG_IS_FLOOR)
1270 const_iv (FLAG_LIFESAVE)
1271 const_iv (FLAG_NO_STRENGTH)
1272 const_iv (FLAG_SLEEP)
1273 const_iv (FLAG_STAND_STILL)
1274 const_iv (FLAG_RANDOM_MOVE)
1275 const_iv (FLAG_ONLY_ATTACK)
1276 const_iv (FLAG_CONFUSED)
1277 const_iv (FLAG_STEALTH)
1278 const_iv (FLAG_WIZPASS)
1279 const_iv (FLAG_IS_LINKED)
1280 const_iv (FLAG_CURSED)
1281 const_iv (FLAG_DAMNED)
1282 const_iv (FLAG_SEE_ANYWHERE)
1283 const_iv (FLAG_KNOWN_MAGICAL)
1284 const_iv (FLAG_KNOWN_CURSED)
1285 const_iv (FLAG_CAN_USE_SKILL)
1286 const_iv (FLAG_BEEN_APPLIED)
1287 const_iv (FLAG_READY_SCROLL)
1288 const_iv (FLAG_USE_ROD)
1289 const_iv (FLAG_USE_HORN)
1290 const_iv (FLAG_MAKE_INVIS)
1291 const_iv (FLAG_INV_LOCKED)
1292 const_iv (FLAG_IS_WOODED)
1293 const_iv (FLAG_IS_HILLY)
1294 const_iv (FLAG_READY_SKILL)
1295 const_iv (FLAG_READY_WEAPON)
1296 const_iv (FLAG_NO_SKILL_IDENT)
1297 const_iv (FLAG_BLIND)
1298 const_iv (FLAG_SEE_IN_DARK)
1299 const_iv (FLAG_IS_CAULDRON)
1300 const_iv (FLAG_NO_STEAL)
1301 const_iv (FLAG_ONE_HIT)
1302 const_iv (FLAG_CLIENT_SENT)
1303 const_iv (FLAG_BERSERK)
1304 const_iv (FLAG_NEUTRAL)
1305 const_iv (FLAG_NO_ATTACK)
1306 const_iv (FLAG_NO_DAMAGE)
1307 const_iv (FLAG_OBJ_ORIGINAL)
1308 const_iv (FLAG_OBJ_SAVE_ON_OVL)
1309 const_iv (FLAG_ACTIVATE_ON_PUSH)
1310 const_iv (FLAG_ACTIVATE_ON_RELEASE)
1311 const_iv (FLAG_IS_WATER)
1312 const_iv (FLAG_CONTENT_ON_GEN)
1313 const_iv (FLAG_IS_A_TEMPLATE)
1314 const_iv (FLAG_IS_BUILDABLE)
1315 const_iv (FLAG_DESTROY_ON_DEATH)
1316 const_iv (FLAG_NO_MAP_SAVE)
1317
1318 const_iv (NDI_BLACK)
1319 const_iv (NDI_WHITE)
1320 const_iv (NDI_NAVY)
1321 const_iv (NDI_RED)
1322 const_iv (NDI_ORANGE)
1323 const_iv (NDI_BLUE)
1324 const_iv (NDI_DK_ORANGE)
1325 const_iv (NDI_GREEN)
1326 const_iv (NDI_LT_GREEN)
1327 const_iv (NDI_GREY)
1328 const_iv (NDI_BROWN)
1329 const_iv (NDI_GOLD)
1330 const_iv (NDI_TAN)
1331 const_iv (NDI_MAX_COLOR)
1332 const_iv (NDI_COLOR_MASK)
1333 const_iv (NDI_UNIQUE)
1334 const_iv (NDI_ALL)
1335
1336 const_iv (UPD_LOCATION)
1337 const_iv (UPD_FLAGS)
1338 const_iv (UPD_WEIGHT)
1339 const_iv (UPD_FACE)
1340 const_iv (UPD_NAME)
1341 const_iv (UPD_ANIM)
1342 const_iv (UPD_ANIMSPEED)
1343 const_iv (UPD_NROF)
1344
1345 const_iv (UPD_SP_MANA)
1346 const_iv (UPD_SP_GRACE)
1347 const_iv (UPD_SP_DAMAGE)
1348
1349 const_iv (F_APPLIED)
1350 const_iv (F_LOCATION)
1351 const_iv (F_UNPAID)
1352 const_iv (F_MAGIC)
1353 const_iv (F_CURSED)
1354 const_iv (F_DAMNED)
1355 const_iv (F_OPEN)
1356 const_iv (F_NOPICK)
1357 const_iv (F_LOCKED)
1358
1359 const_iv (F_BUY)
1360 const_iv (F_SHOP)
1361 const_iv (F_SELL)
1362
1363 const_iv (P_BLOCKSVIEW)
1364 const_iv (P_PLAYER)
1365 const_iv (P_NO_MAGIC)
1366 const_iv (P_IS_ALIVE)
1367 const_iv (P_NO_CLERIC)
1368 const_iv (P_OUT_OF_MAP)
1369 const_iv (P_NEW_MAP)
1370 const_iv (P_UPTODATE)
1371
1372 const_iv (UP_OBJ_INSERT)
1373 const_iv (UP_OBJ_REMOVE)
1374 const_iv (UP_OBJ_CHANGE)
1375 const_iv (UP_OBJ_FACE)
1376
1377 const_iv (INS_NO_MERGE)
1378 const_iv (INS_ABOVE_FLOOR_ONLY)
1379 const_iv (INS_NO_WALK_ON)
1380 const_iv (INS_ON_TOP)
1381 const_iv (INS_BELOW_ORIGINATOR)
1382 const_iv (INS_MAP_LOAD)
1383
1384 const_iv (WILL_APPLY_HANDLE)
1385 const_iv (WILL_APPLY_TREASURE)
1386 const_iv (WILL_APPLY_EARTHWALL)
1387 const_iv (WILL_APPLY_DOOR)
1388 const_iv (WILL_APPLY_FOOD)
1389
1390 const_iv (SAVE_MODE)
1391 const_iv (SAVE_DIR_MODE)
1392
1393 const_iv (M_PAPER)
1394 const_iv (M_IRON)
1395 const_iv (M_GLASS)
1396 const_iv (M_LEATHER)
1397 const_iv (M_WOOD)
1398 const_iv (M_ORGANIC)
1399 const_iv (M_STONE)
1400 const_iv (M_CLOTH)
1401 const_iv (M_ADAMANT)
1402 const_iv (M_LIQUID)
1403 const_iv (M_SOFT_METAL)
1404 const_iv (M_BONE)
1405 const_iv (M_ICE)
1406 const_iv (M_SPECIAL)
1407
1408 const_iv (SK_EXP_ADD_SKILL)
1409 const_iv (SK_EXP_TOTAL)
1410 const_iv (SK_EXP_NONE)
1411 const_iv (SK_SUBTRACT_SKILL_EXP)
1412 const_iv (SK_EXP_SKILL_ONLY)
1413
1414 const_iv (SK_LOCKPICKING)
1415 const_iv (SK_HIDING)
1416 const_iv (SK_SMITHERY)
1417 const_iv (SK_BOWYER)
1418 const_iv (SK_JEWELER)
1419 const_iv (SK_ALCHEMY)
1420 const_iv (SK_STEALING)
1421 const_iv (SK_LITERACY)
1422 const_iv (SK_BARGAINING)
1423 const_iv (SK_JUMPING)
1424 const_iv (SK_DET_MAGIC)
1425 const_iv (SK_ORATORY)
1426 const_iv (SK_SINGING)
1427 const_iv (SK_DET_CURSE)
1428 const_iv (SK_FIND_TRAPS)
1429 const_iv (SK_MEDITATION)
1430 const_iv (SK_PUNCHING)
1431 const_iv (SK_FLAME_TOUCH)
1432 const_iv (SK_KARATE)
1433 const_iv (SK_CLIMBING)
1434 const_iv (SK_WOODSMAN)
1435 const_iv (SK_INSCRIPTION)
1436 const_iv (SK_ONE_HANDED_WEAPON)
1437 const_iv (SK_MISSILE_WEAPON)
1438 const_iv (SK_THROWING)
1439 const_iv (SK_USE_MAGIC_ITEM)
1440 const_iv (SK_DISARM_TRAPS)
1441 const_iv (SK_SET_TRAP)
1442 const_iv (SK_THAUMATURGY)
1443 const_iv (SK_PRAYING)
1444 const_iv (SK_CLAWING)
1445 const_iv (SK_LEVITATION)
1446 const_iv (SK_SUMMONING)
1447 const_iv (SK_PYROMANCY)
1448 const_iv (SK_EVOCATION)
1449 const_iv (SK_SORCERY)
1450 const_iv (SK_TWO_HANDED_WEAPON)
1451 const_iv (SK_SPARK_TOUCH)
1452 const_iv (SK_SHIVER)
1453 const_iv (SK_ACID_SPLASH)
1454 const_iv (SK_POISON_NAIL)
1455
1456 const_iv (SOUND_NEW_PLAYER)
1457 const_iv (SOUND_FIRE_ARROW)
1458 const_iv (SOUND_LEARN_SPELL)
1459 const_iv (SOUND_FUMBLE_SPELL)
1460 const_iv (SOUND_WAND_POOF)
1461 const_iv (SOUND_OPEN_DOOR)
1462 const_iv (SOUND_PUSH_PLAYER)
1463 const_iv (SOUND_PLAYER_HITS1)
1464 const_iv (SOUND_PLAYER_HITS2)
1465 const_iv (SOUND_PLAYER_HITS3)
1466 const_iv (SOUND_PLAYER_HITS4)
1467 const_iv (SOUND_PLAYER_IS_HIT1)
1468 const_iv (SOUND_PLAYER_IS_HIT2)
1469 const_iv (SOUND_PLAYER_IS_HIT3)
1470 const_iv (SOUND_PLAYER_KILLS)
1471 const_iv (SOUND_PET_IS_KILLED)
1472 const_iv (SOUND_PLAYER_DIES)
1473 const_iv (SOUND_OB_EVAPORATE)
1474 const_iv (SOUND_OB_EXPLODE)
1475 const_iv (SOUND_CLOCK)
1476 const_iv (SOUND_TURN_HANDLE)
1477 const_iv (SOUND_FALL_HOLE)
1478 const_iv (SOUND_DRINK_POISON)
1479 const_iv (SOUND_CAST_SPELL_0)
1480
1481 const_iv (PREFER_LOW)
1482 const_iv (PREFER_HIGH)
1483
1484 const_iv (ATNR_PHYSICAL)
1485 const_iv (ATNR_MAGIC)
1486 const_iv (ATNR_FIRE)
1487 const_iv (ATNR_ELECTRICITY)
1488 const_iv (ATNR_COLD)
1489 const_iv (ATNR_CONFUSION)
1490 const_iv (ATNR_ACID)
1491 const_iv (ATNR_DRAIN)
1492 const_iv (ATNR_WEAPONMAGIC)
1493 const_iv (ATNR_GHOSTHIT)
1494 const_iv (ATNR_POISON)
1495 const_iv (ATNR_SLOW)
1496 const_iv (ATNR_PARALYZE)
1497 const_iv (ATNR_TURN_UNDEAD)
1498 const_iv (ATNR_FEAR)
1499 const_iv (ATNR_CANCELLATION)
1500 const_iv (ATNR_DEPLETE)
1501 const_iv (ATNR_DEATH)
1502 const_iv (ATNR_CHAOS)
1503 const_iv (ATNR_COUNTERSPELL)
1504 const_iv (ATNR_GODPOWER)
1505 const_iv (ATNR_HOLYWORD)
1506 const_iv (ATNR_BLIND)
1507 const_iv (ATNR_INTERNAL)
1508 const_iv (ATNR_LIFE_STEALING)
1509 const_iv (ATNR_DISEASE)
1510
1511 const_iv (MAP_IN_MEMORY)
1512 const_iv (MAP_SWAPPED)
1513 const_iv (MAP_LOADING)
1514 const_iv (MAP_SAVING)
1515
1516 const_iv (KLASS_ATTACHABLE)
1517 const_iv (KLASS_GLOBAL)
1518 const_iv (KLASS_OBJECT)
1519 const_iv (KLASS_CLIENT)
1520 const_iv (KLASS_PLAYER)
1521 const_iv (KLASS_MAP)
1522
1523 const_iv (CS_QUERY_YESNO)
1524 const_iv (CS_QUERY_SINGLECHAR)
1525 const_iv (CS_QUERY_HIDEINPUT)
1526
1527 const_iv (ST_DEAD)
1528 const_iv (ST_SETUP)
1529 const_iv (ST_PLAYING)
1530 const_iv (ST_CUSTOM)
1531
1532 const_iv (ST_CHANGE_CLASS)
1533
1534 const_iv (IO_HEADER)
1535 const_iv (IO_OBJECTS)
1536 const_iv (IO_UNIQUES)
1537
1538 // random map generator
1539 const_iv (LAYOUT_NONE)
1540 const_iv (LAYOUT_ONION)
1541 const_iv (LAYOUT_MAZE)
1542 const_iv (LAYOUT_SPIRAL)
1543 const_iv (LAYOUT_ROGUELIKE)
1544 const_iv (LAYOUT_SNAKE)
1545 const_iv (LAYOUT_SQUARE_SPIRAL)
1546
1547 const_iv (RMOPT_RANDOM)
1548 const_iv (RMOPT_CENTERED)
1549 const_iv (RMOPT_LINEAR)
1550 const_iv (RMOPT_BOTTOM_C)
1551 const_iv (RMOPT_BOTTOM_R)
1552 const_iv (RMOPT_IRR_SPACE)
1553 const_iv (RMOPT_WALL_OFF)
1554 const_iv (RMOPT_WALLS_ONLY)
1555 const_iv (RMOPT_NO_DOORS)
1556
1557 const_iv (SYMMETRY_RANDOM)
1558 const_iv (SYMMETRY_NONE)
1559 const_iv (SYMMETRY_X)
1560 const_iv (SYMMETRY_Y)
1561 const_iv (SYMMETRY_XY)
1562 };
1563
1564 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1565 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1566
1567 static const struct {
1568 const char *name;
1569 int skip;
1570 IV klass;
1571 IV iv;
1572 } *eiv, event_iv[] = {
1573 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1574 # include "eventinc.h"
1575 # undef def
1576 };
1577
1578 AV *av = get_av ("cf::EVENT", 1);
1579
1580 for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1581 {
1582 AV *event = newAV ();
1583 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1584 av_push (event, newSViv (eiv->klass));
1585 av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1586 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1587 }
1588 }
1589
1590 void _connect_to_perl ()
1591
1592 void _global_reattach ()
1593 CODE:
1594 {
1595 // reattach to all attachable objects in the game.
1596 for_all_clients (ns)
1597 ns->reattach ();
1598
1599 for_all_objects (op)
1600 op->reattach ();
1601 }
1602
1603 NV floor (NV x)
1604
1605 NV ceil (NV x)
1606
1607 NV rndm (...)
1608 CODE:
1609 switch (items)
1610 {
1611 case 0: RETVAL = rndm (); break;
1612 case 1: RETVAL = rndm (SvUV (ST (0))); break;
1613 case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1614 default: croak ("cf::rndm requires none, one or two parameters."); break;
1615 }
1616 OUTPUT:
1617 RETVAL
1618
1619 void server_tick ()
1620 CODE:
1621 runtime = SvNVx (sv_runtime);
1622 server_tick ();
1623
1624 void
1625 LOG (int level, char *msg)
1626 PROTOTYPE: $$
1627 C_ARGS: (LogLevel)level, "%s", msg
1628
1629 char *path_combine (char *base, char *path)
1630 PROTOTYPE: $$
1631
1632 char *path_combine_and_normalize (char *base, char *path)
1633 PROTOTYPE: $$
1634
1635 const char *
1636 get_maps_directory (char *path)
1637 PROTOTYPE: $
1638 ALIAS: maps_directory = 0
1639 CODE:
1640 RETVAL = create_pathname (path);
1641 OUTPUT: RETVAL
1642
1643 void
1644 sub_generation_inc ()
1645 CODE:
1646 PL_sub_generation++;
1647
1648 char *
1649 mapdir ()
1650 PROTOTYPE:
1651 ALIAS:
1652 mapdir = 0
1653 uniquedir = 1
1654 tmpdir = 2
1655 confdir = 3
1656 localdir = 4
1657 playerdir = 5
1658 datadir = 6
1659 CODE:
1660 switch (ix)
1661 {
1662 case 0: RETVAL = settings.mapdir ; break;
1663 case 1: RETVAL = settings.uniquedir; break;
1664 case 2: RETVAL = settings.tmpdir ; break;
1665 case 3: RETVAL = settings.confdir ; break;
1666 case 4: RETVAL = settings.localdir ; break;
1667 case 5: RETVAL = settings.playerdir; break;
1668 case 6: RETVAL = settings.datadir ; break;
1669 }
1670 OUTPUT: RETVAL
1671
1672 void abort ()
1673
1674 void fork_abort (char *cause = "cf::fork_abort")
1675
1676 void cleanup (const char *cause, bool make_core = false)
1677
1678 void emergency_save ()
1679
1680 void _exit (int status = EXIT_SUCCESS)
1681
1682 UV sv_2watcher (SV *w)
1683 CODE:
1684 RETVAL = (UV)GEventAPI->sv_2watcher (w);
1685 OUTPUT:
1686 RETVAL
1687
1688 #if _POSIX_MEMLOCK
1689
1690 int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1691
1692 int munlockall ()
1693
1694 #endif
1695
1696 int find_animation (char *text)
1697 PROTOTYPE: $
1698
1699 int random_roll (int min, int max, object *op, int goodbad);
1700
1701 const char *cost_string_from_value(uint64 cost, int approx = 0)
1702
1703 int
1704 exp_to_level (val64 exp)
1705 CODE:
1706 {
1707 int i = 0;
1708
1709 RETVAL = settings.max_level;
1710
1711 for (i = 1; i <= settings.max_level; i++)
1712 {
1713 if (levels[i] > exp)
1714 {
1715 RETVAL = i - 1;
1716 break;
1717 }
1718 }
1719 }
1720 OUTPUT: RETVAL
1721
1722 val64
1723 level_to_min_exp (int level)
1724 CODE:
1725 if (level > settings.max_level)
1726 RETVAL = levels[settings.max_level];
1727 else if (level < 1)
1728 RETVAL = 0;
1729 else
1730 RETVAL = levels[level];
1731 OUTPUT: RETVAL
1732
1733 SV *
1734 resistance_to_string (int atnr)
1735 CODE:
1736 if (atnr >= 0 && atnr < NROFATTACKS)
1737 RETVAL = newSVpv (resist_plus[atnr], 0);
1738 else
1739 XSRETURN_UNDEF;
1740 OUTPUT: RETVAL
1741
1742 bool
1743 load_resource_file (const char *filename)
1744
1745 MODULE = cf PACKAGE = cf::attachable
1746
1747 int
1748 valid (SV *obj)
1749 CODE:
1750 RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1751 OUTPUT:
1752 RETVAL
1753
1754 void
1755 debug_trace (attachable *obj, bool on = true)
1756 CODE:
1757 obj->flags &= ~attachable::F_DEBUG_TRACE;
1758 if (on)
1759 obj->flags |= attachable::F_DEBUG_TRACE;
1760
1761 int mortals_size ()
1762 CODE:
1763 RETVAL = attachable::mortals.size ();
1764 OUTPUT: RETVAL
1765
1766 #object *mortals (U32 index)
1767 # CODE:
1768 # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1769 # OUTPUT: RETVAL
1770
1771 INCLUDE: $PERL $srcdir/genacc attachable ../include/cfperl.h |
1772
1773 MODULE = cf PACKAGE = cf::global
1774
1775 int invoke (SV *klass, int event, ...)
1776 CODE:
1777 if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1778 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1779 for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1780 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1781 OUTPUT: RETVAL
1782
1783 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1784
1785 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1786
1787 int invoke (object *op, int event, ...)
1788 CODE:
1789 if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1790 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1791 for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1792 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1793 OUTPUT: RETVAL
1794
1795 SV *registry (object *op)
1796
1797 int objects_size ()
1798 CODE:
1799 RETVAL = objects.size ();
1800 OUTPUT: RETVAL
1801
1802 object *objects (U32 index)
1803 CODE:
1804 RETVAL = index < objects.size () ? objects [index] : 0;
1805 OUTPUT: RETVAL
1806
1807 int actives_size ()
1808 CODE:
1809 RETVAL = actives.size ();
1810 OUTPUT: RETVAL
1811
1812 object *actives (U32 index)
1813 CODE:
1814 RETVAL = index < actives.size () ? actives [index] : 0;
1815 OUTPUT: RETVAL
1816
1817 # missing properties
1818
1819 object *head (object *op)
1820 PROTOTYPE: $
1821 CODE:
1822 RETVAL = op->head_ ();
1823 OUTPUT: RETVAL
1824
1825 int is_head (object *op)
1826 PROTOTYPE: $
1827 CODE:
1828 RETVAL = op->head_ () == op;
1829 OUTPUT: RETVAL
1830
1831 void
1832 inv (object *obj)
1833 PROTOTYPE: $
1834 PPCODE:
1835 {
1836 object *o;
1837 for (o = obj->inv; o; o = o->below)
1838 XPUSHs (sv_2mortal (to_sv (o)));
1839 }
1840
1841 void
1842 set_animation (object *op, int idx)
1843 CODE:
1844 SET_ANIMATION (op, idx);
1845
1846 int
1847 num_animations (object *op)
1848 CODE:
1849 RETVAL = NUM_ANIMATIONS (op);
1850 OUTPUT: RETVAL
1851
1852 object *find_best_object_match (object *op, const char *match)
1853
1854 object *find_marked_object (object *op)
1855
1856 int need_identify (object *obj);
1857
1858 int apply_shop_mat (object *shop_mat, object *op);
1859
1860 int move_player (object *op, int dir)
1861 CODE:
1862 RETVAL = move_player (op, dir);
1863 OUTPUT:
1864 RETVAL
1865
1866 int move (object *op, int dir, object *originator = op)
1867 CODE:
1868 RETVAL = move_ob (op, dir, originator);
1869 OUTPUT:
1870 RETVAL
1871
1872 void apply (object *applier, object *applied, int flags = 0)
1873 CODE:
1874 manual_apply (applied, applier, flags);
1875
1876 void apply_below (object *op)
1877 CODE:
1878 player_apply_below (op);
1879
1880 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1881
1882 object *cf_object_present_archname_inside (object *op, char *whatstr)
1883
1884 int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1885
1886 int cf_object_change_map (object *op, int x, int y, maptile *map)
1887
1888 #//TODO
1889 object *clone_ (object *op, int recursive = 0)
1890 CODE:
1891 if (recursive)
1892 RETVAL = object_create_clone (op);
1893 else
1894 {
1895 RETVAL = object::create ();
1896 op->copy_to (RETVAL);
1897 }
1898 OUTPUT: RETVAL
1899
1900 int pay_item (object *op, object *buyer)
1901 CODE:
1902 RETVAL = pay_for_item (op, buyer);
1903 OUTPUT: RETVAL
1904
1905 int pay_amount (object *op, uint64 amount)
1906 CODE:
1907 RETVAL = pay_for_amount (amount, op);
1908 OUTPUT: RETVAL
1909
1910 void pay_player (object *op, uint64 amount)
1911
1912 val64 pay_player_arch (object *op, const char *arch, uint64 amount)
1913
1914 int cast_spell (object *op, object *caster, int dir, object *spell_ob, char *stringarg = 0)
1915
1916 void learn_spell (object *op, object *sp, int special_prayer = 0)
1917 CODE:
1918 do_learn_spell (op, sp, special_prayer);
1919
1920 void forget_spell (object *op, object *sp)
1921 CODE:
1922 do_forget_spell (op, query_name (sp));
1923
1924 object *check_for_spell (object *op, char *spellname)
1925 CODE:
1926 RETVAL = check_spell_known (op, spellname);
1927 OUTPUT: RETVAL
1928
1929 int query_money (object *op)
1930 ALIAS: money = 0
1931
1932 val64 query_cost (object *op, object *who, int flags)
1933 ALIAS: cost = 0
1934
1935 void spring_trap (object *op, object *victim)
1936
1937 int check_trigger (object *op, object *cause)
1938
1939 void drop (object *who, object *op)
1940
1941 void pick_up (object *who, object *op)
1942
1943 int cf_object_teleport (object *op, maptile *map, int x, int y)
1944
1945 void update_object (object *op, int action)
1946
1947 object *cf_create_object_by_name (const char *name)
1948
1949 void change_exp (object *op, uint64 exp, const char *skill_name = 0, int flag = 0)
1950
1951 void player_lvl_adj (object *who, object *skill = 0)
1952
1953 int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1954
1955 int calc_skill_exp (object *who, object *op, object *skill);
1956
1957 void push_button (object *op);
1958
1959 void use_trigger (object *op);
1960
1961 void add_button_link (object *button, maptile *map, int connected);
1962
1963 void remove_button_link (object *op);
1964
1965
1966 MODULE = cf PACKAGE = cf::object PREFIX = cf_
1967
1968 object *cf_insert_ob_in_ob (object *ob, object *where)
1969
1970 # no clean way to get an object from an archetype - stupid idiotic
1971 # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1972
1973 object *new (const char *archetype = 0)
1974 PROTOTYPE: ;$
1975 CODE:
1976 RETVAL = archetype ? get_archetype (archetype) : cf_create_object ();
1977 OUTPUT:
1978 RETVAL
1979
1980 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1981 PROTOTYPE: $$$$$$
1982 CODE:
1983 {
1984 int unused_type;
1985 RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1986 }
1987
1988 # syntatic sugar for easier use in event callbacks.
1989 const char *options (object *op)
1990 CODE:
1991 RETVAL = op->name;
1992 OUTPUT:
1993 RETVAL
1994
1995 player *contr (object *op)
1996 CODE:
1997 RETVAL = op->contr;
1998 OUTPUT: RETVAL
1999
2000 const char *get_ob_key_value (object *op, const char *key)
2001
2002 bool set_ob_key_value (object *op, const char *key, const char *value = 0, int add_key = 1)
2003
2004 object *get_nearest_player (object *ob)
2005 ALIAS: nearest_player = 0
2006 PREINIT:
2007 extern object *get_nearest_player (object *);
2008
2009 void rangevector (object *ob, object *other, int flags = 0)
2010 PROTOTYPE: $$;$
2011 PPCODE:
2012 {
2013 rv_vector rv;
2014 get_rangevector (ob, other, &rv, flags);
2015 EXTEND (SP, 5);
2016 PUSHs (newSVuv (rv.distance));
2017 PUSHs (newSViv (rv.distance_x));
2018 PUSHs (newSViv (rv.distance_y));
2019 PUSHs (newSViv (rv.direction));
2020 PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
2021 }
2022
2023 bool on_same_map_as (object *ob, object *other)
2024 CODE:
2025 RETVAL = on_same_map (ob, other);
2026 OUTPUT: RETVAL
2027
2028 const char *
2029 base_name (object *op, int plural = op->nrof > 1)
2030 CODE:
2031 RETVAL = query_base_name (op, plural);
2032 OUTPUT: RETVAL
2033
2034 object *decrease_ob_nr (object *op, unsigned long i)
2035
2036 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2037
2038 player *player (object *op)
2039 CODE:
2040 RETVAL = op->contr;
2041 OUTPUT: RETVAL
2042
2043 void check_score (object *op)
2044
2045 void message (object *op, char *txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2046 CODE:
2047 new_draw_info (flags, 0, op, txt);
2048
2049 object *cf_player_send_inventory (object *op)
2050
2051 char *cf_player_get_ip (object *op)
2052 ALIAS: ip = 0
2053
2054 object *cf_player_get_marked_item (object *op)
2055 ALIAS: marked_item = 0
2056
2057 void cf_player_set_marked_item (object *op, object *ob)
2058
2059 partylist *cf_player_get_party (object *op)
2060 ALIAS: party = 0
2061
2062 void cf_player_set_party (object *op, partylist *party)
2063
2064 void kill_player (object *op)
2065
2066 void esrv_update_item (object *op, int what, object *item)
2067 C_ARGS: what, op, item
2068
2069 void clear_los (object *op)
2070
2071 int command_summon (object *op, char *params)
2072
2073 int command_arrest (object *op, char *params)
2074
2075
2076 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2077
2078 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2079
2080 int invoke (player *pl, int event, ...)
2081 CODE:
2082 if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2083 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2084 for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2085 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2086 OUTPUT: RETVAL
2087
2088 SV *registry (player *pl)
2089
2090 void
2091 save_stats (player *pl)
2092 CODE:
2093 pl->ob->stats.hp = pl->ob->stats.maxhp;
2094 pl->ob->stats.sp = pl->ob->stats.maxsp;
2095 pl->ob->stats.grace = pl->ob->stats.maxgrace;
2096 pl->orig_stats = pl->ob->stats;
2097
2098 void cf_player_move (player *pl, int dir)
2099
2100 void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
2101
2102 bool
2103 cell_visible (player *pl, int dx, int dy)
2104 CODE:
2105 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2106 && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2107 OUTPUT:
2108 RETVAL
2109
2110 void
2111 send (player *pl, SV *packet)
2112 CODE:
2113 {
2114 STRLEN len;
2115 char *buf = SvPVbyte (packet, len);
2116
2117 if (pl->ns)
2118 pl->ns->send_packet (buf, len);
2119 }
2120
2121 int
2122 listening (player *pl, int new_value = -1)
2123 CODE:
2124 RETVAL = pl->listening;
2125 if (new_value >= 0)
2126 pl->listening = new_value;
2127 OUTPUT:
2128 RETVAL
2129
2130 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2131 PROTOTYPE: $;$$$
2132 PPCODE:
2133 if (GIMME_V != G_VOID)
2134 {
2135 EXTEND (SP, 3);
2136 PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2137 PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2138 PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2139 }
2140 if (map_path) sv_to (map_path, pl->savebed_map);
2141 if (x) sv_to (x, pl->bed_x);
2142 if (y) sv_to (y, pl->bed_y);
2143
2144 void
2145 list ()
2146 PPCODE:
2147 for_all_players (pl)
2148 XPUSHs (sv_2mortal (to_sv (pl)));
2149
2150
2151 MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2152
2153 int invoke (maptile *map, int event, ...)
2154 CODE:
2155 if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2156 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2157 for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2158 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2159 OUTPUT: RETVAL
2160
2161 SV *registry (maptile *map)
2162
2163 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2164
2165 void
2166 maptile::instantiate ()
2167
2168 maptile *new ()
2169 PROTOTYPE:
2170 CODE:
2171 RETVAL = new maptile;
2172 OUTPUT:
2173 RETVAL
2174
2175 void
2176 maptile::players ()
2177 PPCODE:
2178 if (GIMME_V == G_SCALAR)
2179 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2180 else if (GIMME_V == G_ARRAY)
2181 {
2182 EXTEND (SP, THIS->players);
2183 for_all_players (pl)
2184 if (pl->ob && pl->ob->map == THIS)
2185 PUSHs (sv_2mortal (to_sv (pl->ob)));
2186 }
2187
2188 void
2189 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2190 CODE:
2191 {
2192 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2193 croak ("maptile::add_underlay: palette must be arrayref");
2194
2195 palette = SvRV (palette);
2196
2197 STRLEN idxlen;
2198 const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2199
2200 for (int x = 0; x < THIS->width; ++x)
2201 for (int y = 0; y < THIS->height; ++y)
2202 {
2203 for (object *op = THIS->at (x, y).bot; op; op = op->above)
2204 if (op->flag [FLAG_IS_FLOOR])
2205 goto skip_space;
2206
2207 {
2208 int offs = offset + y * stride + x;
2209 if (IN_RANGE_EXC (offs, 0, idxlen))
2210 {
2211 if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2212 {
2213 object *ob = get_archetype (SvPVutf8_nolen (*elem));
2214 ob->flag [FLAG_NO_MAP_SAVE] = true;
2215 THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2216 }
2217 }
2218 }
2219
2220 skip_space: ;
2221 }
2222 }
2223
2224 void
2225 maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2226 CODE:
2227 {
2228 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2229 croak ("maptile::set_regiondata: palette must be arrayref");
2230
2231 palette = SvRV (palette);
2232
2233 STRLEN idxlen;
2234 const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2235
2236 region **regionmap = (region **)malloc (
2237 (av_len ((AV *)palette) + 1) * sizeof (region *));
2238 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2239
2240 for (int i = av_len ((AV *)palette) + 1; i--; )
2241 regionmap [i] = region::find (
2242 SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2243
2244 for (int y = 0; y < THIS->height; ++y)
2245 memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2246
2247 sfree (THIS->regions, THIS->size ());
2248 free (THIS->regionmap);
2249
2250 THIS->regions = regions;
2251 THIS->regionmap = regionmap;
2252 }
2253
2254 void play_sound_map (maptile *map, int x, int y, int sound_num)
2255
2256 int out_of_map (maptile *map, int x, int y)
2257
2258 void
2259 trigger (maptile *map, long connection, bool state = true)
2260 CODE:
2261 activate_connection (map, connection, state);
2262
2263 void
2264 get_connection (maptile *map, long connection)
2265 PPCODE:
2266 oblinkpt *obp = get_connection_links (map, connection);
2267 if (obp)
2268 for (objectlink *ol = obp->link; ol; ol = ol->next)
2269 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2270
2271 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2272
2273 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2274
2275 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2276 C_ARGS: str, map, nx, ny
2277
2278 void
2279 get_map_flags (maptile *map, int x, int y)
2280 PPCODE:
2281 {
2282 maptile *nmap = 0;
2283 I16 nx = 0, ny = 0;
2284 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2285
2286 EXTEND (SP, 4);
2287 PUSHs (sv_2mortal (newSViv (flags)));
2288
2289 if (GIMME_V == G_ARRAY)
2290 {
2291 PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2292 PUSHs (sv_2mortal (newSViv (nx)));
2293 PUSHs (sv_2mortal (newSViv (ny)));
2294 }
2295 }
2296
2297 void
2298 at (maptile *map, unsigned int x, unsigned int y)
2299 PROTOTYPE: $$$
2300 PPCODE:
2301 {
2302 object *o;
2303 maptile *nmap = 0;
2304 I16 nx, ny;
2305
2306 get_map_flags (map, &nmap, x, y, &nx, &ny);
2307
2308 if (nmap)
2309 for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2310 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2311 }
2312
2313 SV *
2314 bot_at (maptile *obj, unsigned int x, unsigned int y)
2315 PROTOTYPE: $$$
2316 ALIAS:
2317 top_at = 1
2318 flags_at = 2
2319 light_at = 3
2320 move_block_at = 4
2321 move_slow_at = 5
2322 move_on_at = 6
2323 move_off_at = 7
2324 INIT:
2325 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2326 CODE:
2327 switch (ix)
2328 {
2329 case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2330 case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2331 case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2332 case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2333 case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2334 case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2335 case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2336 case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2337 }
2338 OUTPUT: RETVAL
2339
2340 void fix_walls (maptile *map, int x, int y)
2341
2342 void fix_walls_around (maptile *map, int x, int y)
2343
2344 # worst xs function of my life
2345 bool
2346 _create_random_map (\
2347 maptile *self,\
2348 char *wallstyle,\
2349 char *wall_name,\
2350 char *floorstyle,\
2351 char *monsterstyle,\
2352 char *treasurestyle,\
2353 char *layoutstyle,\
2354 char *doorstyle,\
2355 char *decorstyle,\
2356 char *origin_map,\
2357 char *final_map,\
2358 char *exitstyle,\
2359 char *this_map,\
2360 char *exit_on_final_map,\
2361 int xsize,\
2362 int ysize,\
2363 int expand2x,\
2364 int layoutoptions1,\
2365 int layoutoptions2,\
2366 int layoutoptions3,\
2367 int symmetry,\
2368 int difficulty,\
2369 int difficulty_given,\
2370 float difficulty_increase,\
2371 int dungeon_level,\
2372 int dungeon_depth,\
2373 int decoroptions,\
2374 int orientation,\
2375 int origin_y,\
2376 int origin_x,\
2377 U32 random_seed,\
2378 val64 total_map_hp,\
2379 int map_layout_style,\
2380 int treasureoptions,\
2381 int symmetry_used,\
2382 region *region,\
2383 char *custom\
2384 )
2385 CODE:
2386 {
2387 random_map_params rmp;
2388
2389 assign (rmp.wallstyle , wallstyle);
2390 assign (rmp.wall_name , wall_name);
2391 assign (rmp.floorstyle , floorstyle);
2392 assign (rmp.monsterstyle , monsterstyle);
2393 assign (rmp.treasurestyle , treasurestyle);
2394 assign (rmp.layoutstyle , layoutstyle);
2395 assign (rmp.doorstyle , doorstyle);
2396 assign (rmp.decorstyle , decorstyle);
2397 assign (rmp.exitstyle , exitstyle);
2398 assign (rmp.exit_on_final_map, exit_on_final_map);
2399
2400 rmp.origin_map = origin_map;
2401 rmp.final_map = final_map;
2402 rmp.this_map = this_map;
2403 rmp.xsize = xsize;
2404 rmp.ysize = ysize;
2405 rmp.expand2x = expand2x;
2406 rmp.layoutoptions1 = layoutoptions1;
2407 rmp.layoutoptions2 = layoutoptions2;
2408 rmp.layoutoptions3 = layoutoptions3;
2409 rmp.symmetry = symmetry;
2410 rmp.difficulty = difficulty;
2411 rmp.difficulty_given = difficulty_given;
2412 rmp.difficulty_increase = difficulty_increase;
2413 rmp.dungeon_level = dungeon_level;
2414 rmp.dungeon_depth = dungeon_depth;
2415 rmp.decoroptions = decoroptions;
2416 rmp.orientation = orientation;
2417 rmp.origin_y = origin_y;
2418 rmp.origin_x = origin_x;
2419 rmp.random_seed = random_seed;
2420 rmp.total_map_hp = total_map_hp;
2421 rmp.map_layout_style = map_layout_style;
2422 rmp.treasureoptions = treasureoptions;
2423 rmp.symmetry_used = symmetry_used;
2424 rmp.region = region;
2425 rmp.custom = custom;
2426
2427 RETVAL = self->generate_random_map (&rmp);
2428 }
2429 OUTPUT:
2430 RETVAL
2431
2432 MODULE = cf PACKAGE = cf::arch
2433
2434 archetype *find (const char *name)
2435 CODE:
2436 RETVAL = archetype::find (name);
2437 OUTPUT:
2438 RETVAL
2439
2440 archetype *first()
2441 PROTOTYPE:
2442 CODE:
2443 RETVAL = first_archetype;
2444 OUTPUT: RETVAL
2445
2446 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2447
2448 MODULE = cf PACKAGE = cf::party
2449
2450 partylist *first ()
2451 PROTOTYPE:
2452 CODE:
2453 RETVAL = get_firstparty ();
2454 OUTPUT: RETVAL
2455
2456 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2457
2458 MODULE = cf PACKAGE = cf::region
2459
2460 void
2461 list ()
2462 PPCODE:
2463 for_all_regions (rgn)
2464 XPUSHs (sv_2mortal (to_sv (rgn)));
2465
2466 region *find (char *name)
2467 PROTOTYPE: $
2468 CODE:
2469 RETVAL = region::find (name);
2470 OUTPUT: RETVAL
2471
2472 region *find_fuzzy (char *name)
2473 PROTOTYPE: $
2474 CODE:
2475 RETVAL = region::find_fuzzy (name);
2476 OUTPUT: RETVAL
2477
2478 INCLUDE: $PERL $srcdir/genacc region ../include/map.h |
2479
2480 MODULE = cf PACKAGE = cf::living
2481
2482 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2483
2484 MODULE = cf PACKAGE = cf::settings
2485
2486 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2487
2488 MODULE = cf PACKAGE = cf::client
2489
2490 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2491
2492 int invoke (client *ns, int event, ...)
2493 CODE:
2494 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2495 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2496 for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2497 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2498 OUTPUT: RETVAL
2499
2500 SV *registry (client *ns)
2501
2502 void
2503 list ()
2504 PPCODE:
2505 EXTEND (SP, clients.size ());
2506 for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2507 PUSHs (sv_2mortal (to_sv (*i)));
2508
2509 void
2510 client::send_packet (SV *packet)
2511 CODE:
2512 {
2513 STRLEN len;
2514 char *buf = SvPVbyte (packet, len);
2515
2516 THIS->send_packet (buf, len);
2517 }
2518
2519 MODULE = cf PACKAGE = cf::face PREFIX = face_
2520
2521 INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2522
2523 faceidx face_find (const char *name, faceidx defidx = 0)
2524
2525 faceidx alloc (const char *name)
2526 CODE:
2527 {
2528 do
2529 {
2530 RETVAL = faces.size ();
2531 faces.resize (RETVAL + 1);
2532 }
2533 while (!RETVAL); // crude way to leave index 0
2534
2535 faces [RETVAL].name = name;
2536 facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2537
2538 if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2539 if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2540 }
2541 OUTPUT: RETVAL
2542
2543 void set (faceidx idx, int visibility, int magicmap)
2544 CODE:
2545 faceinfo *f = face_info (idx);
2546 assert (f);
2547 f->visibility = visibility;
2548 f->magicmap = magicmap;
2549
2550 void set_smooth (faceidx idx, faceidx smooth)
2551 CODE:
2552 faceinfo *f = face_info (idx);
2553 assert (f);
2554 f->smooth = smooth;
2555
2556 void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2557 CODE:
2558 facedata *d = face_data (idx, faceset);
2559 assert (d);
2560 assert (sv_len (chksum) == CHKSUM_SIZE);
2561 sv_to (data, d->data); memcpy (d->chksum, SvPVbyte_nolen (chksum), CHKSUM_SIZE);
2562
2563 void invalidate (faceidx idx)
2564 CODE:
2565 for_all_clients (ns)
2566 ns->faces_sent [idx] = 0;
2567
2568 void invalidate_all ()
2569 CODE:
2570 for_all_clients (ns)
2571 memset (ns->faces_sent, 0, sizeof (ns->faces_sent));
2572