ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.148
Committed: Sat Jan 20 23:39:09 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.147: +0 -6 lines
Log Message:
*** empty log message ***

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