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