ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.198
Committed: Fri Apr 27 19:53:05 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.197: +31 -4 lines
Log Message:
revamp loggin. have a new log flag logBacktrace that logs
the message and prepares a backtrace in the background, spewing
it into the log at a later time.

this is useful to shed some light on otherwise completely useless log
messages such as:

   2007-04-27 19:48:48.142 Calling random_roll with min=1 max=0

which could just as well not be there as we will never find out who is
doing this to puny poor random_roll.

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