ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.150
Committed: Tue Jan 23 01:05:18 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.149: +21 -9 lines
Log Message:
- avoid negative event priorities like the plague. they are actually
  worse because they introduce random memory corruption and endless
  loops and worse, if worse exists.
- aggressively swap out maps when #actives exceeds threshold
- sweep and cede after server tick
- increase player command handling priorities, just in case.
- fix a bug in mortal checking, this was the reason for the
  enourmous memory leaks in map-world.ext
- mark c++-side watchers as non-reentrant

File Contents

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