ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.152
Committed: Tue Jan 23 03:17:56 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.151: +4 -8 lines
Log Message:
- weirdify refcounting:
  objects still keep their natural refcount of zero
  do not borrow anymore, seems the right thing to do *right now*

File Contents

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