ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.211
Committed: Sat May 19 11:19:03 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.210: +0 -15 lines
Log Message:
rmeove funcitons likely calling abort anyway

File Contents

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