ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.210
Committed: Sat May 19 00:08:12 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.209: +60 -8 lines
Log Message:
- optimise invoke by using an inline check on a bitset (kind of a simplified
  bloom filter for all events).

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     object *cf_player_send_inventory (object *op)
1948    
1949 root 1.183 octet_string cf_player_get_ip (object *op)
1950 root 1.1 ALIAS: ip = 0
1951    
1952     object *cf_player_get_marked_item (object *op)
1953     ALIAS: marked_item = 0
1954    
1955     void cf_player_set_marked_item (object *op, object *ob)
1956    
1957     partylist *cf_player_get_party (object *op)
1958     ALIAS: party = 0
1959    
1960     void cf_player_set_party (object *op, partylist *party)
1961    
1962     void kill_player (object *op)
1963    
1964 root 1.58 void esrv_update_item (object *op, int what, object *item)
1965     C_ARGS: what, op, item
1966    
1967 root 1.66 void clear_los (object *op)
1968    
1969 root 1.183 int command_summon (object *op, utf8_string params)
1970 root 1.67
1971 root 1.183 int command_arrest (object *op, utf8_string params)
1972 root 1.67
1973 root 1.66
1974 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
1975 root 1.1
1976 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
1977 root 1.62
1978 root 1.18 int invoke (player *pl, int event, ...)
1979     CODE:
1980     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
1981 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1982     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1983 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
1984 root 1.18 OUTPUT: RETVAL
1985    
1986 root 1.12 SV *registry (player *pl)
1987 root 1.1
1988 root 1.102 void
1989     save_stats (player *pl)
1990     CODE:
1991     pl->ob->stats.hp = pl->ob->stats.maxhp;
1992     pl->ob->stats.sp = pl->ob->stats.maxsp;
1993     pl->ob->stats.grace = pl->ob->stats.maxgrace;
1994     pl->orig_stats = pl->ob->stats;
1995    
1996 root 1.1 void cf_player_move (player *pl, int dir)
1997    
1998     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
1999    
2000     bool
2001     cell_visible (player *pl, int dx, int dy)
2002     CODE:
2003 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2004     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2005 root 1.1 OUTPUT:
2006     RETVAL
2007    
2008 root 1.4 void
2009 root 1.1 send (player *pl, SV *packet)
2010     CODE:
2011     {
2012     STRLEN len;
2013     char *buf = SvPVbyte (packet, len);
2014    
2015 root 1.100 if (pl->ns)
2016     pl->ns->send_packet (buf, len);
2017 root 1.1 }
2018    
2019     int
2020     listening (player *pl, int new_value = -1)
2021     CODE:
2022     RETVAL = pl->listening;
2023     if (new_value >= 0)
2024     pl->listening = new_value;
2025     OUTPUT:
2026     RETVAL
2027    
2028 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2029 root 1.45 PROTOTYPE: $;$$$
2030 root 1.1 PPCODE:
2031 root 1.45 if (GIMME_V != G_VOID)
2032     {
2033     EXTEND (SP, 3);
2034     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2035     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2036     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2037     }
2038 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2039     if (x) sv_to (x, pl->bed_x);
2040     if (y) sv_to (y, pl->bed_y);
2041 root 1.1
2042     void
2043     list ()
2044     PPCODE:
2045 root 1.128 for_all_players (pl)
2046 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2047 root 1.1
2048    
2049     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2050    
2051 root 1.61 int invoke (maptile *map, int event, ...)
2052 root 1.18 CODE:
2053     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2054 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2055     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2056 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2057 root 1.25 OUTPUT: RETVAL
2058 root 1.18
2059 root 1.61 SV *registry (maptile *map)
2060 root 1.12
2061 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2062 root 1.1
2063 root 1.116 void
2064     maptile::instantiate ()
2065    
2066     maptile *new ()
2067 root 1.1 PROTOTYPE:
2068     CODE:
2069 root 1.116 RETVAL = new maptile;
2070 root 1.1 OUTPUT:
2071     RETVAL
2072    
2073 root 1.116 void
2074 root 1.117 maptile::players ()
2075     PPCODE:
2076     if (GIMME_V == G_SCALAR)
2077 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2078 root 1.117 else if (GIMME_V == G_ARRAY)
2079     {
2080     EXTEND (SP, THIS->players);
2081     for_all_players (pl)
2082     if (pl->ob && pl->ob->map == THIS)
2083 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2084 root 1.117 }
2085    
2086 root 1.156 void
2087 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2088 root 1.156 CODE:
2089     {
2090 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2091     croak ("maptile::add_underlay: palette must be arrayref");
2092 root 1.156
2093 root 1.168 palette = SvRV (palette);
2094 root 1.156
2095 root 1.168 STRLEN idxlen;
2096     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2097 root 1.156
2098 root 1.168 for (int x = 0; x < THIS->width; ++x)
2099     for (int y = 0; y < THIS->height; ++y)
2100     {
2101     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2102     if (op->flag [FLAG_IS_FLOOR])
2103     goto skip_space;
2104    
2105     {
2106     int offs = offset + y * stride + x;
2107     if (IN_RANGE_EXC (offs, 0, idxlen))
2108     {
2109     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2110     {
2111     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2112     ob->flag [FLAG_NO_MAP_SAVE] = true;
2113     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2114 root 1.200
2115     if (ob->randomitems)
2116     {
2117 root 1.203 if (!ob->above)
2118     {
2119     ob->create_treasure (ob->randomitems);
2120    
2121     for (object *op = ob->above; op; op = op->above)
2122     op->flag [FLAG_NO_MAP_SAVE] = true;
2123     }
2124    
2125 root 1.200 ob->randomitems = 0;
2126     }
2127 root 1.168 }
2128     }
2129     }
2130 root 1.156
2131 root 1.168 skip_space: ;
2132     }
2133     }
2134    
2135     void
2136     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2137     CODE:
2138     {
2139     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2140     croak ("maptile::set_regiondata: palette must be arrayref");
2141    
2142     palette = SvRV (palette);
2143    
2144     STRLEN idxlen;
2145     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2146    
2147     region **regionmap = (region **)malloc (
2148     (av_len ((AV *)palette) + 1) * sizeof (region *));
2149     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2150    
2151     for (int i = av_len ((AV *)palette) + 1; i--; )
2152     regionmap [i] = region::find (
2153     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2154    
2155     for (int y = 0; y < THIS->height; ++y)
2156     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2157    
2158     sfree (THIS->regions, THIS->size ());
2159     free (THIS->regionmap);
2160    
2161     THIS->regions = regions;
2162 root 1.156 THIS->regionmap = regionmap;
2163     }
2164    
2165 root 1.193 void
2166     maptile::create_region_treasure ()
2167     CODE:
2168     {
2169     object *op = object::create ();
2170     op->type = FLOOR;
2171     op->map = THIS;
2172    
2173     for (int x = 0; x < THIS->width; ++x)
2174     for (int y = 0; y < THIS->height; ++y)
2175     {
2176     region *rgn = THIS->region (x, y);
2177    
2178     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2179     if (rgn->treasure && rndm () < rgn->treasure_density)
2180     {
2181     op->x = x;
2182     op->y = y;
2183     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2184     }
2185     }
2186    
2187     op->destroy ();
2188     }
2189    
2190 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2191 root 1.1
2192 root 1.74 int out_of_map (maptile *map, int x, int y)
2193    
2194 root 1.29 void
2195 root 1.61 trigger (maptile *map, long connection, bool state = true)
2196 root 1.29 CODE:
2197     activate_connection (map, connection, state);
2198    
2199     void
2200 root 1.61 get_connection (maptile *map, long connection)
2201 root 1.29 PPCODE:
2202     oblinkpt *obp = get_connection_links (map, connection);
2203     if (obp)
2204     for (objectlink *ol = obp->link; ol; ol = ol->next)
2205 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2206 root 1.29
2207 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2208 root 1.1
2209 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2210 root 1.1
2211 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2212 root 1.1 C_ARGS: str, map, nx, ny
2213    
2214     void
2215 root 1.140 get_map_flags (maptile *map, int x, int y)
2216 root 1.1 PPCODE:
2217     {
2218 root 1.61 maptile *nmap = 0;
2219 root 1.1 I16 nx = 0, ny = 0;
2220 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2221 root 1.1
2222     EXTEND (SP, 4);
2223     PUSHs (sv_2mortal (newSViv (flags)));
2224    
2225     if (GIMME_V == G_ARRAY)
2226     {
2227     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2228     PUSHs (sv_2mortal (newSViv (nx)));
2229     PUSHs (sv_2mortal (newSViv (ny)));
2230     }
2231     }
2232    
2233     void
2234 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2235 root 1.1 PROTOTYPE: $$$
2236     PPCODE:
2237     {
2238     object *o;
2239 root 1.61 maptile *nmap = 0;
2240 root 1.1 I16 nx, ny;
2241    
2242 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2243 root 1.1
2244     if (nmap)
2245     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2246     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2247     }
2248    
2249     SV *
2250 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2251 root 1.1 PROTOTYPE: $$$
2252     ALIAS:
2253     top_at = 1
2254     flags_at = 2
2255     light_at = 3
2256     move_block_at = 4
2257     move_slow_at = 5
2258     move_on_at = 6
2259     move_off_at = 7
2260     INIT:
2261 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2262 root 1.1 CODE:
2263     switch (ix)
2264     {
2265     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2266     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2267     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2268     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2269     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2270     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2271     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2272     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2273     }
2274 root 1.122 OUTPUT: RETVAL
2275 root 1.1
2276 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2277    
2278     void fix_walls_around (maptile *map, int x, int y)
2279 root 1.1
2280 root 1.117 # worst xs function of my life
2281 root 1.140 bool
2282 root 1.117 _create_random_map (\
2283 root 1.140 maptile *self,\
2284 root 1.183 utf8_string wallstyle,\
2285     utf8_string wall_name,\
2286     utf8_string floorstyle,\
2287     utf8_string monsterstyle,\
2288     utf8_string treasurestyle,\
2289     utf8_string layoutstyle,\
2290     utf8_string doorstyle,\
2291     utf8_string decorstyle,\
2292     utf8_string origin_map,\
2293     utf8_string final_map,\
2294     utf8_string exitstyle,\
2295     utf8_string this_map,\
2296     utf8_string exit_on_final_map,\
2297 root 1.146 int xsize,\
2298     int ysize,\
2299 root 1.117 int expand2x,\
2300     int layoutoptions1,\
2301     int layoutoptions2,\
2302     int layoutoptions3,\
2303     int symmetry,\
2304     int difficulty,\
2305     int difficulty_given,\
2306     float difficulty_increase,\
2307     int dungeon_level,\
2308     int dungeon_depth,\
2309     int decoroptions,\
2310     int orientation,\
2311     int origin_y,\
2312     int origin_x,\
2313 root 1.146 U32 random_seed,\
2314 root 1.117 val64 total_map_hp,\
2315     int map_layout_style,\
2316     int treasureoptions,\
2317     int symmetry_used,\
2318 root 1.137 region *region,\
2319 root 1.183 utf8_string custom\
2320 root 1.117 )
2321     CODE:
2322     {
2323     random_map_params rmp;
2324    
2325     assign (rmp.wallstyle , wallstyle);
2326     assign (rmp.wall_name , wall_name);
2327     assign (rmp.floorstyle , floorstyle);
2328     assign (rmp.monsterstyle , monsterstyle);
2329     assign (rmp.treasurestyle , treasurestyle);
2330     assign (rmp.layoutstyle , layoutstyle);
2331     assign (rmp.doorstyle , doorstyle);
2332     assign (rmp.decorstyle , decorstyle);
2333     assign (rmp.exitstyle , exitstyle);
2334     assign (rmp.exit_on_final_map, exit_on_final_map);
2335    
2336 root 1.122 rmp.origin_map = origin_map;
2337     rmp.final_map = final_map;
2338     rmp.this_map = this_map;
2339 root 1.146 rmp.xsize = xsize;
2340     rmp.ysize = ysize;
2341 root 1.117 rmp.expand2x = expand2x;
2342     rmp.layoutoptions1 = layoutoptions1;
2343     rmp.layoutoptions2 = layoutoptions2;
2344     rmp.layoutoptions3 = layoutoptions3;
2345     rmp.symmetry = symmetry;
2346     rmp.difficulty = difficulty;
2347     rmp.difficulty_given = difficulty_given;
2348     rmp.difficulty_increase = difficulty_increase;
2349     rmp.dungeon_level = dungeon_level;
2350     rmp.dungeon_depth = dungeon_depth;
2351     rmp.decoroptions = decoroptions;
2352     rmp.orientation = orientation;
2353     rmp.origin_y = origin_y;
2354     rmp.origin_x = origin_x;
2355     rmp.random_seed = random_seed;
2356     rmp.total_map_hp = total_map_hp;
2357     rmp.map_layout_style = map_layout_style;
2358     rmp.treasureoptions = treasureoptions;
2359     rmp.symmetry_used = symmetry_used;
2360     rmp.region = region;
2361 root 1.137 rmp.custom = custom;
2362 root 1.117
2363 root 1.140 RETVAL = self->generate_random_map (&rmp);
2364 root 1.117 }
2365     OUTPUT:
2366     RETVAL
2367    
2368 root 1.19 MODULE = cf PACKAGE = cf::arch
2369 root 1.1
2370 root 1.183 archetype *find (utf8_string name)
2371 elmex 1.36 CODE:
2372 root 1.60 RETVAL = archetype::find (name);
2373 elmex 1.36 OUTPUT:
2374     RETVAL
2375    
2376 root 1.19 archetype *first()
2377 root 1.1 PROTOTYPE:
2378 root 1.19 CODE:
2379     RETVAL = first_archetype;
2380     OUTPUT: RETVAL
2381 root 1.1
2382 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2383 root 1.1
2384 root 1.19 MODULE = cf PACKAGE = cf::party
2385 root 1.1
2386 root 1.19 partylist *first ()
2387 root 1.1 PROTOTYPE:
2388 root 1.19 CODE:
2389     RETVAL = get_firstparty ();
2390     OUTPUT: RETVAL
2391 root 1.1
2392 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2393 root 1.1
2394 root 1.19 MODULE = cf PACKAGE = cf::region
2395 root 1.1
2396 root 1.161 void
2397     list ()
2398     PPCODE:
2399     for_all_regions (rgn)
2400     XPUSHs (sv_2mortal (to_sv (rgn)));
2401    
2402 root 1.183 region *find (utf8_string name)
2403 root 1.161 PROTOTYPE: $
2404 root 1.19 CODE:
2405 root 1.161 RETVAL = region::find (name);
2406 root 1.19 OUTPUT: RETVAL
2407 root 1.1
2408 root 1.183 region *find_fuzzy (utf8_string name)
2409 root 1.122 PROTOTYPE: $
2410     CODE:
2411 root 1.161 RETVAL = region::find_fuzzy (name);
2412 root 1.122 OUTPUT: RETVAL
2413    
2414 root 1.186 int specificity (region *rgn)
2415     CODE:
2416     RETVAL = 0;
2417     while (rgn = rgn->parent)
2418     RETVAL++;
2419     OUTPUT: RETVAL
2420    
2421 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2422 root 1.1
2423 root 1.19 MODULE = cf PACKAGE = cf::living
2424 root 1.1
2425 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2426 root 1.1
2427 root 1.76 MODULE = cf PACKAGE = cf::settings
2428    
2429 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2430 root 1.76
2431 root 1.84 MODULE = cf PACKAGE = cf::client
2432 root 1.79
2433 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2434 root 1.79
2435 root 1.84 int invoke (client *ns, int event, ...)
2436 root 1.79 CODE:
2437 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2438 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2439     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2440 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2441 root 1.79 OUTPUT: RETVAL
2442    
2443 root 1.84 SV *registry (client *ns)
2444 root 1.79
2445 root 1.100 void
2446     list ()
2447     PPCODE:
2448     EXTEND (SP, clients.size ());
2449     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2450     PUSHs (sv_2mortal (to_sv (*i)));
2451    
2452 root 1.88 void
2453 root 1.100 client::send_packet (SV *packet)
2454     CODE:
2455     {
2456     STRLEN len;
2457     char *buf = SvPVbyte (packet, len);
2458    
2459     THIS->send_packet (buf, len);
2460     }
2461    
2462 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2463    
2464 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2465 root 1.176
2466 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2467 root 1.176
2468 root 1.183 faceidx alloc (utf8_string name)
2469 root 1.176 CODE:
2470     {
2471     do
2472     {
2473     RETVAL = faces.size ();
2474 root 1.177 faces.resize (RETVAL + 1);
2475 root 1.176 }
2476     while (!RETVAL); // crude way to leave index 0
2477    
2478     faces [RETVAL].name = name;
2479     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2480    
2481     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2482     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2483     }
2484     OUTPUT: RETVAL
2485    
2486 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2487 root 1.176 CODE:
2488 root 1.177 faceinfo *f = face_info (idx);
2489     assert (f);
2490     f->visibility = visibility;
2491     f->magicmap = magicmap;
2492 root 1.176
2493 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2494 root 1.177 CODE:
2495 root 1.184 faceinfo *f = face_info (idx); assert (f);
2496     f->smooth = smooth;
2497     f->smoothlevel = smoothlevel;
2498 root 1.177
2499     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2500 root 1.176 CODE:
2501 root 1.182 {
2502 root 1.176 facedata *d = face_data (idx, faceset);
2503 root 1.177 assert (d);
2504 root 1.181 sv_to (data, d->data);
2505     STRLEN clen;
2506     char *cdata = SvPVbyte (chksum, clen);
2507 root 1.182 clen = min (CHKSUM_SIZE, clen);
2508    
2509     if (memcmp (d->chksum, cdata, clen))
2510     {
2511     memcpy (d->chksum, cdata, clen);
2512    
2513     // invalidate existing client face info
2514     for_all_clients (ns)
2515     if (ns->faceset == faceset)
2516     {
2517     ns->faces_sent [idx] = false;
2518     ns->force_newmap = true;
2519     }
2520     }
2521     }
2522 root 1.176
2523 root 1.177 void invalidate (faceidx idx)
2524     CODE:
2525     for_all_clients (ns)
2526 root 1.182 {
2527     ns->faces_sent [idx] = false;
2528     ns->force_newmap = true;
2529     }
2530 root 1.177
2531     void invalidate_all ()
2532     CODE:
2533     for_all_clients (ns)
2534 root 1.182 {
2535     ns->faces_sent.reset ();
2536     ns->force_newmap = true;
2537     }
2538 root 1.177
2539 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2540    
2541     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2542    
2543     animidx anim_find (utf8_string name)
2544     CODE:
2545     RETVAL = animation::find (name).number;
2546     OUTPUT: RETVAL
2547    
2548     animidx set (utf8_string name, SV *frames, int facings = 1)
2549     CODE:
2550     {
2551     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2552     croak ("frames must be an arrayref");
2553    
2554     AV *av = (AV *)SvRV (frames);
2555    
2556     animation *anim = &animation::find (name);
2557     if (anim->number)
2558     {
2559     anim->resize (av_len (av) + 1);
2560     anim->facings = facings;
2561     }
2562     else
2563     anim = &animation::create (name, av_len (av) + 1, facings);
2564    
2565     for (int i = 0; i < anim->num_animations; ++i)
2566     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2567     }
2568     OUTPUT: RETVAL
2569    
2570     void invalidate_all ()
2571     CODE:
2572     for_all_clients (ns)
2573     ns->anims_sent.reset ();
2574