ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.153
Committed: Fri Jan 26 20:59:57 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.152: +32 -17 lines
Log Message:
- tame the map/map-world.ext a bit to avoid potential memleaks for now
- object refcounting was borked, fixed, again :)
- add cf::attacahble::mortals_size
- disable reset-after-load, this is unsafe due to locking issues, so don't do it
- make map-scheduler configurable
- improve emergency swap mode
- prepare_random_map must be a sync job for now :(
- do not keep object reference in enter_exit, the object might have been gone already.
- nuke cf::object::mortals.

File Contents

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