ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.203
Committed: Sun Apr 29 14:33:33 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.202: +8 -1 lines
Log Message:
stop unnatural growth on map save (hopefully)

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.199 void reset_signals ()
1468    
1469 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1470 root 1.144
1471 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1472 root 1.134
1473 root 1.116 void emergency_save ()
1474    
1475 root 1.156 void _exit (int status = EXIT_SUCCESS)
1476    
1477 root 1.149 UV sv_2watcher (SV *w)
1478     CODE:
1479     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1480     OUTPUT:
1481     RETVAL
1482    
1483 root 1.125 #if _POSIX_MEMLOCK
1484    
1485     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1486    
1487     int munlockall ()
1488    
1489     #endif
1490    
1491 root 1.183 int find_animation (utf8_string text)
1492 root 1.1 PROTOTYPE: $
1493    
1494 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1495 root 1.1
1496 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1497 root 1.1
1498     int
1499     exp_to_level (val64 exp)
1500     CODE:
1501     {
1502     int i = 0;
1503    
1504     RETVAL = settings.max_level;
1505    
1506     for (i = 1; i <= settings.max_level; i++)
1507     {
1508     if (levels[i] > exp)
1509     {
1510     RETVAL = i - 1;
1511     break;
1512     }
1513     }
1514     }
1515     OUTPUT: RETVAL
1516    
1517     val64
1518     level_to_min_exp (int level)
1519     CODE:
1520     if (level > settings.max_level)
1521     RETVAL = levels[settings.max_level];
1522     else if (level < 1)
1523     RETVAL = 0;
1524     else
1525     RETVAL = levels[level];
1526     OUTPUT: RETVAL
1527    
1528     SV *
1529     resistance_to_string (int atnr)
1530     CODE:
1531     if (atnr >= 0 && atnr < NROFATTACKS)
1532     RETVAL = newSVpv (resist_plus[atnr], 0);
1533     else
1534     XSRETURN_UNDEF;
1535     OUTPUT: RETVAL
1536    
1537 root 1.162 bool
1538 root 1.183 load_resource_file (octet_string filename)
1539 root 1.162
1540 root 1.97 MODULE = cf PACKAGE = cf::attachable
1541    
1542 root 1.27 int
1543 root 1.97 valid (SV *obj)
1544 root 1.27 CODE:
1545     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1546     OUTPUT:
1547     RETVAL
1548    
1549 root 1.164 void
1550     debug_trace (attachable *obj, bool on = true)
1551     CODE:
1552     obj->flags &= ~attachable::F_DEBUG_TRACE;
1553     if (on)
1554     obj->flags |= attachable::F_DEBUG_TRACE;
1555    
1556 root 1.153 int mortals_size ()
1557     CODE:
1558     RETVAL = attachable::mortals.size ();
1559     OUTPUT: RETVAL
1560    
1561     #object *mortals (U32 index)
1562     # CODE:
1563     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1564     # OUTPUT: RETVAL
1565    
1566 root 1.173 INCLUDE: $PERL $srcdir/genacc attachable ../include/cfperl.h |
1567 root 1.115
1568 root 1.101 MODULE = cf PACKAGE = cf::global
1569    
1570     int invoke (SV *klass, int event, ...)
1571     CODE:
1572     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1573     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1574     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1575 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1576 root 1.101 OUTPUT: RETVAL
1577    
1578 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1579    
1580 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1581 root 1.62
1582 root 1.18 int invoke (object *op, int event, ...)
1583     CODE:
1584     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1585 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1586     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1587 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1588 root 1.18 OUTPUT: RETVAL
1589    
1590     SV *registry (object *op)
1591    
1592 root 1.134 int objects_size ()
1593     CODE:
1594     RETVAL = objects.size ();
1595     OUTPUT: RETVAL
1596    
1597     object *objects (U32 index)
1598     CODE:
1599     RETVAL = index < objects.size () ? objects [index] : 0;
1600     OUTPUT: RETVAL
1601    
1602     int actives_size ()
1603     CODE:
1604     RETVAL = actives.size ();
1605     OUTPUT: RETVAL
1606    
1607     object *actives (U32 index)
1608 root 1.57 CODE:
1609 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1610 root 1.57 OUTPUT: RETVAL
1611    
1612 root 1.1 # missing properties
1613    
1614 root 1.54 object *head (object *op)
1615     PROTOTYPE: $
1616     CODE:
1617 root 1.134 RETVAL = op->head_ ();
1618 root 1.54 OUTPUT: RETVAL
1619    
1620     int is_head (object *op)
1621     PROTOTYPE: $
1622     CODE:
1623 root 1.134 RETVAL = op->head_ () == op;
1624 root 1.54 OUTPUT: RETVAL
1625    
1626 root 1.1 void
1627     inv (object *obj)
1628     PROTOTYPE: $
1629     PPCODE:
1630     {
1631     object *o;
1632     for (o = obj->inv; o; o = o->below)
1633 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1634 root 1.1 }
1635    
1636 root 1.102 void
1637     set_animation (object *op, int idx)
1638     CODE:
1639     SET_ANIMATION (op, idx);
1640    
1641 elmex 1.160 int
1642     num_animations (object *op)
1643     CODE:
1644     RETVAL = NUM_ANIMATIONS (op);
1645     OUTPUT: RETVAL
1646    
1647 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1648 root 1.58
1649     object *find_marked_object (object *op)
1650    
1651 root 1.109 int need_identify (object *obj);
1652 root 1.1
1653     int apply_shop_mat (object *shop_mat, object *op);
1654    
1655 pippijn 1.172 int move_player (object *op, int dir)
1656     CODE:
1657     RETVAL = move_player (op, dir);
1658     OUTPUT:
1659     RETVAL
1660    
1661 root 1.27 int move (object *op, int dir, object *originator = op)
1662     CODE:
1663     RETVAL = move_ob (op, dir, originator);
1664     OUTPUT:
1665     RETVAL
1666 root 1.1
1667 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1668     CODE:
1669     manual_apply (applied, applier, flags);
1670 root 1.1
1671 root 1.74 void apply_below (object *op)
1672     CODE:
1673     player_apply_below (op);
1674 root 1.1
1675 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1676    
1677 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1678 root 1.1
1679     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1680    
1681 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1682 root 1.1
1683 root 1.116 #//TODO
1684     object *clone_ (object *op, int recursive = 0)
1685 root 1.74 CODE:
1686     if (recursive)
1687     RETVAL = object_create_clone (op);
1688     else
1689     {
1690     RETVAL = object::create ();
1691 root 1.75 op->copy_to (RETVAL);
1692 root 1.74 }
1693     OUTPUT: RETVAL
1694 root 1.1
1695 root 1.74 int pay_item (object *op, object *buyer)
1696     CODE:
1697     RETVAL = pay_for_item (op, buyer);
1698     OUTPUT: RETVAL
1699 root 1.1
1700 root 1.74 int pay_amount (object *op, uint64 amount)
1701     CODE:
1702     RETVAL = pay_for_amount (amount, op);
1703     OUTPUT: RETVAL
1704 root 1.1
1705     void pay_player (object *op, uint64 amount)
1706    
1707 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1708 root 1.1
1709 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1710 root 1.1
1711 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1712     CODE:
1713     do_learn_spell (op, sp, special_prayer);
1714 root 1.1
1715 root 1.74 void forget_spell (object *op, object *sp)
1716     CODE:
1717     do_forget_spell (op, query_name (sp));
1718 root 1.1
1719 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1720 root 1.74 CODE:
1721     RETVAL = check_spell_known (op, spellname);
1722     OUTPUT: RETVAL
1723 root 1.1
1724 root 1.74 int query_money (object *op)
1725 root 1.1 ALIAS: money = 0
1726    
1727 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1728 root 1.1 ALIAS: cost = 0
1729    
1730 root 1.74 void spring_trap (object *op, object *victim)
1731 root 1.1
1732 root 1.74 int check_trigger (object *op, object *cause)
1733 root 1.1
1734 root 1.74 void drop (object *who, object *op)
1735 root 1.1
1736 root 1.74 void pick_up (object *who, object *op)
1737 root 1.1
1738 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
1739 root 1.1
1740 root 1.102 void update_object (object *op, int action)
1741 root 1.1
1742 root 1.183 object *cf_create_object_by_name (utf8_string name)
1743 root 1.1
1744 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
1745 root 1.1
1746     void player_lvl_adj (object *who, object *skill = 0)
1747    
1748     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1749    
1750     int calc_skill_exp (object *who, object *op, object *skill);
1751    
1752     void push_button (object *op);
1753    
1754     void use_trigger (object *op);
1755    
1756 root 1.61 void add_button_link (object *button, maptile *map, int connected);
1757 root 1.1
1758     void remove_button_link (object *op);
1759    
1760    
1761     MODULE = cf PACKAGE = cf::object PREFIX = cf_
1762    
1763     object *cf_insert_ob_in_ob (object *ob, object *where)
1764    
1765     # no clean way to get an object from an archetype - stupid idiotic
1766     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1767    
1768 root 1.183 object *new (utf8_string archetype = 0)
1769 root 1.1 PROTOTYPE: ;$
1770     CODE:
1771     RETVAL = archetype ? get_archetype (archetype) : cf_create_object ();
1772     OUTPUT:
1773     RETVAL
1774    
1775 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1776 root 1.1 PROTOTYPE: $$$$$$
1777     CODE:
1778     {
1779     int unused_type;
1780     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1781     }
1782    
1783     player *contr (object *op)
1784     CODE:
1785     RETVAL = op->contr;
1786     OUTPUT: RETVAL
1787    
1788 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
1789 root 1.1
1790 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
1791 root 1.1
1792     object *get_nearest_player (object *ob)
1793     ALIAS: nearest_player = 0
1794     PREINIT:
1795     extern object *get_nearest_player (object *);
1796    
1797     void rangevector (object *ob, object *other, int flags = 0)
1798     PROTOTYPE: $$;$
1799     PPCODE:
1800     {
1801     rv_vector rv;
1802     get_rangevector (ob, other, &rv, flags);
1803     EXTEND (SP, 5);
1804     PUSHs (newSVuv (rv.distance));
1805     PUSHs (newSViv (rv.distance_x));
1806     PUSHs (newSViv (rv.distance_y));
1807     PUSHs (newSViv (rv.direction));
1808     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
1809     }
1810    
1811     bool on_same_map_as (object *ob, object *other)
1812     CODE:
1813     RETVAL = on_same_map (ob, other);
1814     OUTPUT: RETVAL
1815    
1816 root 1.183 const_utf8_string
1817 root 1.58 base_name (object *op, int plural = op->nrof > 1)
1818 root 1.1 CODE:
1819 root 1.58 RETVAL = query_base_name (op, plural);
1820 root 1.1 OUTPUT: RETVAL
1821    
1822 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
1823    
1824 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
1825    
1826     player *player (object *op)
1827     CODE:
1828     RETVAL = op->contr;
1829     OUTPUT: RETVAL
1830    
1831 root 1.105 void check_score (object *op)
1832    
1833 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
1834 root 1.120 CODE:
1835     new_draw_info (flags, 0, op, txt);
1836 root 1.1
1837     object *cf_player_send_inventory (object *op)
1838    
1839 root 1.183 octet_string cf_player_get_ip (object *op)
1840 root 1.1 ALIAS: ip = 0
1841    
1842     object *cf_player_get_marked_item (object *op)
1843     ALIAS: marked_item = 0
1844    
1845     void cf_player_set_marked_item (object *op, object *ob)
1846    
1847     partylist *cf_player_get_party (object *op)
1848     ALIAS: party = 0
1849    
1850     void cf_player_set_party (object *op, partylist *party)
1851    
1852     void kill_player (object *op)
1853    
1854 root 1.58 void esrv_update_item (object *op, int what, object *item)
1855     C_ARGS: what, op, item
1856    
1857 root 1.66 void clear_los (object *op)
1858    
1859 root 1.183 int command_summon (object *op, utf8_string params)
1860 root 1.67
1861 root 1.183 int command_arrest (object *op, utf8_string params)
1862 root 1.67
1863 root 1.66
1864 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
1865 root 1.1
1866 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
1867 root 1.62
1868 root 1.18 int invoke (player *pl, int event, ...)
1869     CODE:
1870     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
1871 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1872     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1873 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
1874 root 1.18 OUTPUT: RETVAL
1875    
1876 root 1.12 SV *registry (player *pl)
1877 root 1.1
1878 root 1.102 void
1879     save_stats (player *pl)
1880     CODE:
1881     pl->ob->stats.hp = pl->ob->stats.maxhp;
1882     pl->ob->stats.sp = pl->ob->stats.maxsp;
1883     pl->ob->stats.grace = pl->ob->stats.maxgrace;
1884     pl->orig_stats = pl->ob->stats;
1885    
1886 root 1.1 void cf_player_move (player *pl, int dir)
1887    
1888     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
1889    
1890     bool
1891     cell_visible (player *pl, int dx, int dy)
1892     CODE:
1893 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
1894     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
1895 root 1.1 OUTPUT:
1896     RETVAL
1897    
1898 root 1.4 void
1899 root 1.1 send (player *pl, SV *packet)
1900     CODE:
1901     {
1902     STRLEN len;
1903     char *buf = SvPVbyte (packet, len);
1904    
1905 root 1.100 if (pl->ns)
1906     pl->ns->send_packet (buf, len);
1907 root 1.1 }
1908    
1909     int
1910     listening (player *pl, int new_value = -1)
1911     CODE:
1912     RETVAL = pl->listening;
1913     if (new_value >= 0)
1914     pl->listening = new_value;
1915     OUTPUT:
1916     RETVAL
1917    
1918 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
1919 root 1.45 PROTOTYPE: $;$$$
1920 root 1.1 PPCODE:
1921 root 1.45 if (GIMME_V != G_VOID)
1922     {
1923     EXTEND (SP, 3);
1924     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
1925     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
1926     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
1927     }
1928 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
1929     if (x) sv_to (x, pl->bed_x);
1930     if (y) sv_to (y, pl->bed_y);
1931 root 1.1
1932     void
1933     list ()
1934     PPCODE:
1935 root 1.128 for_all_players (pl)
1936 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
1937 root 1.1
1938    
1939     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
1940    
1941 root 1.61 int invoke (maptile *map, int event, ...)
1942 root 1.18 CODE:
1943     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
1944 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1945     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1946 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
1947 root 1.25 OUTPUT: RETVAL
1948 root 1.18
1949 root 1.61 SV *registry (maptile *map)
1950 root 1.12
1951 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
1952 root 1.1
1953 root 1.116 void
1954     maptile::instantiate ()
1955    
1956     maptile *new ()
1957 root 1.1 PROTOTYPE:
1958     CODE:
1959 root 1.116 RETVAL = new maptile;
1960 root 1.1 OUTPUT:
1961     RETVAL
1962    
1963 root 1.116 void
1964 root 1.117 maptile::players ()
1965     PPCODE:
1966     if (GIMME_V == G_SCALAR)
1967 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
1968 root 1.117 else if (GIMME_V == G_ARRAY)
1969     {
1970     EXTEND (SP, THIS->players);
1971     for_all_players (pl)
1972     if (pl->ob && pl->ob->map == THIS)
1973 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
1974 root 1.117 }
1975    
1976 root 1.156 void
1977 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
1978 root 1.156 CODE:
1979     {
1980 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
1981     croak ("maptile::add_underlay: palette must be arrayref");
1982 root 1.156
1983 root 1.168 palette = SvRV (palette);
1984 root 1.156
1985 root 1.168 STRLEN idxlen;
1986     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
1987 root 1.156
1988 root 1.168 for (int x = 0; x < THIS->width; ++x)
1989     for (int y = 0; y < THIS->height; ++y)
1990     {
1991     for (object *op = THIS->at (x, y).bot; op; op = op->above)
1992     if (op->flag [FLAG_IS_FLOOR])
1993     goto skip_space;
1994    
1995     {
1996     int offs = offset + y * stride + x;
1997     if (IN_RANGE_EXC (offs, 0, idxlen))
1998     {
1999     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2000     {
2001     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2002     ob->flag [FLAG_NO_MAP_SAVE] = true;
2003     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2004 root 1.200
2005     if (ob->randomitems)
2006     {
2007 root 1.203 if (!ob->above)
2008     {
2009     ob->create_treasure (ob->randomitems);
2010    
2011     for (object *op = ob->above; op; op = op->above)
2012     op->flag [FLAG_NO_MAP_SAVE] = true;
2013     }
2014    
2015 root 1.200 ob->randomitems = 0;
2016     }
2017 root 1.168 }
2018     }
2019     }
2020 root 1.156
2021 root 1.168 skip_space: ;
2022     }
2023     }
2024    
2025     void
2026     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2027     CODE:
2028     {
2029     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2030     croak ("maptile::set_regiondata: palette must be arrayref");
2031    
2032     palette = SvRV (palette);
2033    
2034     STRLEN idxlen;
2035     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2036    
2037     region **regionmap = (region **)malloc (
2038     (av_len ((AV *)palette) + 1) * sizeof (region *));
2039     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2040    
2041     for (int i = av_len ((AV *)palette) + 1; i--; )
2042     regionmap [i] = region::find (
2043     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2044    
2045     for (int y = 0; y < THIS->height; ++y)
2046     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2047    
2048     sfree (THIS->regions, THIS->size ());
2049     free (THIS->regionmap);
2050    
2051     THIS->regions = regions;
2052 root 1.156 THIS->regionmap = regionmap;
2053     }
2054    
2055 root 1.193 void
2056     maptile::create_region_treasure ()
2057     CODE:
2058     {
2059     object *op = object::create ();
2060     op->type = FLOOR;
2061     op->map = THIS;
2062    
2063     for (int x = 0; x < THIS->width; ++x)
2064     for (int y = 0; y < THIS->height; ++y)
2065     {
2066     region *rgn = THIS->region (x, y);
2067    
2068     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2069     if (rgn->treasure && rndm () < rgn->treasure_density)
2070     {
2071     op->x = x;
2072     op->y = y;
2073     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2074     }
2075     }
2076    
2077     op->destroy ();
2078     }
2079    
2080 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2081 root 1.1
2082 root 1.74 int out_of_map (maptile *map, int x, int y)
2083    
2084 root 1.29 void
2085 root 1.61 trigger (maptile *map, long connection, bool state = true)
2086 root 1.29 CODE:
2087     activate_connection (map, connection, state);
2088    
2089     void
2090 root 1.61 get_connection (maptile *map, long connection)
2091 root 1.29 PPCODE:
2092     oblinkpt *obp = get_connection_links (map, connection);
2093     if (obp)
2094     for (objectlink *ol = obp->link; ol; ol = ol->next)
2095 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2096 root 1.29
2097 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2098 root 1.1
2099 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2100 root 1.1
2101 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2102 root 1.1 C_ARGS: str, map, nx, ny
2103    
2104     void
2105 root 1.140 get_map_flags (maptile *map, int x, int y)
2106 root 1.1 PPCODE:
2107     {
2108 root 1.61 maptile *nmap = 0;
2109 root 1.1 I16 nx = 0, ny = 0;
2110 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2111 root 1.1
2112     EXTEND (SP, 4);
2113     PUSHs (sv_2mortal (newSViv (flags)));
2114    
2115     if (GIMME_V == G_ARRAY)
2116     {
2117     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2118     PUSHs (sv_2mortal (newSViv (nx)));
2119     PUSHs (sv_2mortal (newSViv (ny)));
2120     }
2121     }
2122    
2123     void
2124 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2125 root 1.1 PROTOTYPE: $$$
2126     PPCODE:
2127     {
2128     object *o;
2129 root 1.61 maptile *nmap = 0;
2130 root 1.1 I16 nx, ny;
2131    
2132 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2133 root 1.1
2134     if (nmap)
2135     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2136     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2137     }
2138    
2139     SV *
2140 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2141 root 1.1 PROTOTYPE: $$$
2142     ALIAS:
2143     top_at = 1
2144     flags_at = 2
2145     light_at = 3
2146     move_block_at = 4
2147     move_slow_at = 5
2148     move_on_at = 6
2149     move_off_at = 7
2150     INIT:
2151 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2152 root 1.1 CODE:
2153     switch (ix)
2154     {
2155     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2156     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2157     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2158     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2159     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2160     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2161     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2162     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2163     }
2164 root 1.122 OUTPUT: RETVAL
2165 root 1.1
2166 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2167    
2168     void fix_walls_around (maptile *map, int x, int y)
2169 root 1.1
2170 root 1.117 # worst xs function of my life
2171 root 1.140 bool
2172 root 1.117 _create_random_map (\
2173 root 1.140 maptile *self,\
2174 root 1.183 utf8_string wallstyle,\
2175     utf8_string wall_name,\
2176     utf8_string floorstyle,\
2177     utf8_string monsterstyle,\
2178     utf8_string treasurestyle,\
2179     utf8_string layoutstyle,\
2180     utf8_string doorstyle,\
2181     utf8_string decorstyle,\
2182     utf8_string origin_map,\
2183     utf8_string final_map,\
2184     utf8_string exitstyle,\
2185     utf8_string this_map,\
2186     utf8_string exit_on_final_map,\
2187 root 1.146 int xsize,\
2188     int ysize,\
2189 root 1.117 int expand2x,\
2190     int layoutoptions1,\
2191     int layoutoptions2,\
2192     int layoutoptions3,\
2193     int symmetry,\
2194     int difficulty,\
2195     int difficulty_given,\
2196     float difficulty_increase,\
2197     int dungeon_level,\
2198     int dungeon_depth,\
2199     int decoroptions,\
2200     int orientation,\
2201     int origin_y,\
2202     int origin_x,\
2203 root 1.146 U32 random_seed,\
2204 root 1.117 val64 total_map_hp,\
2205     int map_layout_style,\
2206     int treasureoptions,\
2207     int symmetry_used,\
2208 root 1.137 region *region,\
2209 root 1.183 utf8_string custom\
2210 root 1.117 )
2211     CODE:
2212     {
2213     random_map_params rmp;
2214    
2215     assign (rmp.wallstyle , wallstyle);
2216     assign (rmp.wall_name , wall_name);
2217     assign (rmp.floorstyle , floorstyle);
2218     assign (rmp.monsterstyle , monsterstyle);
2219     assign (rmp.treasurestyle , treasurestyle);
2220     assign (rmp.layoutstyle , layoutstyle);
2221     assign (rmp.doorstyle , doorstyle);
2222     assign (rmp.decorstyle , decorstyle);
2223     assign (rmp.exitstyle , exitstyle);
2224     assign (rmp.exit_on_final_map, exit_on_final_map);
2225    
2226 root 1.122 rmp.origin_map = origin_map;
2227     rmp.final_map = final_map;
2228     rmp.this_map = this_map;
2229 root 1.146 rmp.xsize = xsize;
2230     rmp.ysize = ysize;
2231 root 1.117 rmp.expand2x = expand2x;
2232     rmp.layoutoptions1 = layoutoptions1;
2233     rmp.layoutoptions2 = layoutoptions2;
2234     rmp.layoutoptions3 = layoutoptions3;
2235     rmp.symmetry = symmetry;
2236     rmp.difficulty = difficulty;
2237     rmp.difficulty_given = difficulty_given;
2238     rmp.difficulty_increase = difficulty_increase;
2239     rmp.dungeon_level = dungeon_level;
2240     rmp.dungeon_depth = dungeon_depth;
2241     rmp.decoroptions = decoroptions;
2242     rmp.orientation = orientation;
2243     rmp.origin_y = origin_y;
2244     rmp.origin_x = origin_x;
2245     rmp.random_seed = random_seed;
2246     rmp.total_map_hp = total_map_hp;
2247     rmp.map_layout_style = map_layout_style;
2248     rmp.treasureoptions = treasureoptions;
2249     rmp.symmetry_used = symmetry_used;
2250     rmp.region = region;
2251 root 1.137 rmp.custom = custom;
2252 root 1.117
2253 root 1.140 RETVAL = self->generate_random_map (&rmp);
2254 root 1.117 }
2255     OUTPUT:
2256     RETVAL
2257    
2258 root 1.19 MODULE = cf PACKAGE = cf::arch
2259 root 1.1
2260 root 1.183 archetype *find (utf8_string name)
2261 elmex 1.36 CODE:
2262 root 1.60 RETVAL = archetype::find (name);
2263 elmex 1.36 OUTPUT:
2264     RETVAL
2265    
2266 root 1.19 archetype *first()
2267 root 1.1 PROTOTYPE:
2268 root 1.19 CODE:
2269     RETVAL = first_archetype;
2270     OUTPUT: RETVAL
2271 root 1.1
2272 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2273 root 1.1
2274 root 1.19 MODULE = cf PACKAGE = cf::party
2275 root 1.1
2276 root 1.19 partylist *first ()
2277 root 1.1 PROTOTYPE:
2278 root 1.19 CODE:
2279     RETVAL = get_firstparty ();
2280     OUTPUT: RETVAL
2281 root 1.1
2282 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2283 root 1.1
2284 root 1.19 MODULE = cf PACKAGE = cf::region
2285 root 1.1
2286 root 1.161 void
2287     list ()
2288     PPCODE:
2289     for_all_regions (rgn)
2290     XPUSHs (sv_2mortal (to_sv (rgn)));
2291    
2292 root 1.183 region *find (utf8_string name)
2293 root 1.161 PROTOTYPE: $
2294 root 1.19 CODE:
2295 root 1.161 RETVAL = region::find (name);
2296 root 1.19 OUTPUT: RETVAL
2297 root 1.1
2298 root 1.183 region *find_fuzzy (utf8_string name)
2299 root 1.122 PROTOTYPE: $
2300     CODE:
2301 root 1.161 RETVAL = region::find_fuzzy (name);
2302 root 1.122 OUTPUT: RETVAL
2303    
2304 root 1.186 int specificity (region *rgn)
2305     CODE:
2306     RETVAL = 0;
2307     while (rgn = rgn->parent)
2308     RETVAL++;
2309     OUTPUT: RETVAL
2310    
2311 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2312 root 1.1
2313 root 1.19 MODULE = cf PACKAGE = cf::living
2314 root 1.1
2315 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2316 root 1.1
2317 root 1.76 MODULE = cf PACKAGE = cf::settings
2318    
2319 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2320 root 1.76
2321 root 1.84 MODULE = cf PACKAGE = cf::client
2322 root 1.79
2323 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2324 root 1.79
2325 root 1.84 int invoke (client *ns, int event, ...)
2326 root 1.79 CODE:
2327 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2328 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2329     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2330 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2331 root 1.79 OUTPUT: RETVAL
2332    
2333 root 1.84 SV *registry (client *ns)
2334 root 1.79
2335 root 1.100 void
2336     list ()
2337     PPCODE:
2338     EXTEND (SP, clients.size ());
2339     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2340     PUSHs (sv_2mortal (to_sv (*i)));
2341    
2342 root 1.88 void
2343 root 1.100 client::send_packet (SV *packet)
2344     CODE:
2345     {
2346     STRLEN len;
2347     char *buf = SvPVbyte (packet, len);
2348    
2349     THIS->send_packet (buf, len);
2350     }
2351    
2352 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2353    
2354 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2355 root 1.176
2356 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2357 root 1.176
2358 root 1.183 faceidx alloc (utf8_string name)
2359 root 1.176 CODE:
2360     {
2361     do
2362     {
2363     RETVAL = faces.size ();
2364 root 1.177 faces.resize (RETVAL + 1);
2365 root 1.176 }
2366     while (!RETVAL); // crude way to leave index 0
2367    
2368     faces [RETVAL].name = name;
2369     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2370    
2371     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2372     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2373     }
2374     OUTPUT: RETVAL
2375    
2376 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2377 root 1.176 CODE:
2378 root 1.177 faceinfo *f = face_info (idx);
2379     assert (f);
2380     f->visibility = visibility;
2381     f->magicmap = magicmap;
2382 root 1.176
2383 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2384 root 1.177 CODE:
2385 root 1.184 faceinfo *f = face_info (idx); assert (f);
2386     f->smooth = smooth;
2387     f->smoothlevel = smoothlevel;
2388 root 1.177
2389     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2390 root 1.176 CODE:
2391 root 1.182 {
2392 root 1.176 facedata *d = face_data (idx, faceset);
2393 root 1.177 assert (d);
2394 root 1.181 sv_to (data, d->data);
2395     STRLEN clen;
2396     char *cdata = SvPVbyte (chksum, clen);
2397 root 1.182 clen = min (CHKSUM_SIZE, clen);
2398    
2399     if (memcmp (d->chksum, cdata, clen))
2400     {
2401     memcpy (d->chksum, cdata, clen);
2402    
2403     // invalidate existing client face info
2404     for_all_clients (ns)
2405     if (ns->faceset == faceset)
2406     {
2407     ns->faces_sent [idx] = false;
2408     ns->force_newmap = true;
2409     }
2410     }
2411     }
2412 root 1.176
2413 root 1.177 void invalidate (faceidx idx)
2414     CODE:
2415     for_all_clients (ns)
2416 root 1.182 {
2417     ns->faces_sent [idx] = false;
2418     ns->force_newmap = true;
2419     }
2420 root 1.177
2421     void invalidate_all ()
2422     CODE:
2423     for_all_clients (ns)
2424 root 1.182 {
2425     ns->faces_sent.reset ();
2426     ns->force_newmap = true;
2427     }
2428 root 1.177
2429 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2430    
2431     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2432    
2433     animidx anim_find (utf8_string name)
2434     CODE:
2435     RETVAL = animation::find (name).number;
2436     OUTPUT: RETVAL
2437    
2438     animidx set (utf8_string name, SV *frames, int facings = 1)
2439     CODE:
2440     {
2441     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2442     croak ("frames must be an arrayref");
2443    
2444     AV *av = (AV *)SvRV (frames);
2445    
2446     animation *anim = &animation::find (name);
2447     if (anim->number)
2448     {
2449     anim->resize (av_len (av) + 1);
2450     anim->facings = facings;
2451     }
2452     else
2453     anim = &animation::create (name, av_len (av) + 1, facings);
2454    
2455     for (int i = 0; i < anim->num_animations; ++i)
2456     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2457     }
2458     OUTPUT: RETVAL
2459    
2460     void invalidate_all ()
2461     CODE:
2462     for_all_clients (ns)
2463     ns->anims_sent.reset ();
2464