ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.154
Committed: Fri Jan 26 21:44:11 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.153: +12 -4 lines
Log Message:
- sv_unmagic calls free, which svrefcnt_decs, which in turn will free
  the scalar, leavign sv_unmagic running on invalid memory, so keep
  an extra refcount around sv_unmagic to delay destruction.
  should be abstracted into an attachable_unmagic method.

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