ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.215
Committed: Sun May 27 23:56:21 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.214: +4 -6 lines
Log Message:
more cleanups

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 root 1.214 INVOKE_ATTACHABLE (DESTROY, this);
174 root 1.109
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 root 1.214 INVOKE_ATTACHABLE (INSTANTIATE, this, ARG_STRING (attach));
661 root 1.109 attach = 0;
662     }
663     }
664    
665     void
666     attachable::reattach ()
667     {
668     optimise ();
669     //TODO: check for _attachment's, very important for restarts
670 root 1.214 INVOKE_ATTACHABLE (REATTACH, this);
671 root 1.109 }
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.214 attachable::invoke (event_type event, ...)
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.214 va_list ap;
846     va_start (ap, event);
847    
848 root 1.116 CALL_BEGIN (3);
849     CALL_ARG_SV (newSViv (event)); // only used for debugging nowadays
850     CALL_ARG_SV (newRV_noinc ((SV *)callbacks));
851 root 1.8
852 root 1.109 //TODO: unhack
853 root 1.116 if (object *op = is_a<object>(this)) CALL_ARG_SV (newSVdt (DT_OBJECT, op));
854     else if (player *pl = is_a<player>(this)) CALL_ARG_SV (newSVdt (DT_PLAYER, pl));
855     else if (client *ns = is_a<client>(this)) CALL_ARG_SV (newSVdt (DT_CLIENT, ns));
856     else if (maptile *m = is_a<maptile>(this)) CALL_ARG_SV (newSVdt (DT_MAP, m));
857 root 1.109 else if (global *gl = is_a<global>(this)) /*nop*/;
858     else
859     abort (); //TODO
860 root 1.7
861 root 1.6 for (;;)
862     {
863 root 1.8 dt = (data_type) va_arg (ap, int);
864 root 1.6
865     if (dt == DT_END)
866     break;
867 root 1.109 else if (dt == DT_AV)
868 root 1.12 {
869     AV *av = va_arg (ap, AV *);
870    
871     for (int i = 0; i <= av_len (av); ++i)
872     XPUSHs (*av_fetch (av, i, 1));
873     }
874     else
875     XPUSHs (sv_2mortal (newSVdt_va (ap, dt)));
876 root 1.6 }
877    
878     va_end (ap);
879    
880 root 1.116 CALL_CALL ("cf::do_invoke", G_SCALAR);
881 root 1.6 count = count > 0 ? POPi : 0;
882    
883 root 1.116 CALL_END;
884 root 1.6
885     return count;
886 root 1.2 }
887    
888 root 1.12 SV *
889     cfperl_result (int idx)
890     {
891     AV *av = get_av ("cfperl::invoke_results", 0);
892     if (!av)
893     return &PL_sv_undef;
894    
895     SV **sv = av_fetch (av, idx, 0);
896     if (!sv)
897     return &PL_sv_undef;
898    
899     return *sv;
900     }
901    
902     int
903     cfperl_result_INT (int idx)
904     {
905     return SvIV (cfperl_result (idx));
906     }
907    
908 root 1.74 double
909 root 1.73 cfperl_result_DOUBLE (int idx)
910     {
911     return SvNV (cfperl_result (idx));
912     }
913    
914 root 1.80 /////////////////////////////////////////////////////////////////////////////
915    
916 root 1.116 void
917 root 1.134 cfperl_emergency_save ()
918 root 1.116 {
919     CALL_BEGIN (0);
920 root 1.134 CALL_CALL ("cf::emergency_save", G_VOID);
921 root 1.116 CALL_END;
922     }
923    
924 root 1.165 void
925     cfperl_cleanup (int make_core)
926     {
927     CALL_BEGIN (1);
928     CALL_ARG (make_core);
929     CALL_CALL ("cf::post_cleanup", G_VOID);
930     CALL_END;
931     }
932    
933 root 1.213 void
934     cfperl_make_book (object *book, int level)
935     {
936     CALL_BEGIN (2);
937     CALL_ARG (book);
938     CALL_ARG (level);
939     CALL_CALL ("ext::books::make_book", G_VOID);
940     CALL_END;
941     }
942    
943 root 1.116 maptile *
944 root 1.126 maptile::find_sync (const char *path, maptile *origin)
945 root 1.116 {
946     CALL_BEGIN (2);
947     CALL_ARG (path);
948     CALL_ARG (origin);
949 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
950 root 1.116
951     maptile *retval;
952    
953     if (count)
954     sv_to (POPs, retval);
955     else
956     retval = 0;
957    
958     CALL_END;
959    
960     return retval;
961     }
962    
963 root 1.135 maptile *
964     maptile::find_async (const char *path, maptile *origin)
965     {
966     CALL_BEGIN (2);
967     CALL_ARG (path);
968     CALL_ARG (origin);
969     CALL_CALL ("cf::map::find_async", G_SCALAR);
970    
971     maptile *retval;
972    
973     if (count)
974     sv_to (POPs, retval);
975     else
976     retval = 0;
977    
978     CALL_END;
979    
980     return retval;
981     }
982    
983 root 1.116 void
984 root 1.126 maptile::do_load_sync ()
985     {
986     CALL_BEGIN (1);
987     CALL_ARG (this);
988     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
989     CALL_END;
990     }
991    
992     void
993 root 1.116 maptile::change_all_map_light (int change)
994     {
995     CALL_BEGIN (1);
996     CALL_ARG (change);
997     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
998     CALL_END;
999     }
1000    
1001     void
1002     object::enter_exit (object *exit)
1003     {
1004     if (type != PLAYER)
1005     return;
1006    
1007     CALL_BEGIN (2);
1008     CALL_ARG (this);
1009     CALL_ARG (exit);
1010     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
1011     CALL_END;
1012     }
1013    
1014 root 1.198 void
1015     log_backtrace (const char *msg)
1016     {
1017     #if HAVE_BACKTRACE
1018     void *addr [20];
1019     int size = backtrace (addr, 20);
1020    
1021     CALL_BEGIN (size);
1022     CALL_ARG (msg);
1023     for (int i = 0; i < size; ++i)
1024     CALL_ARG ((IV)addr [i]);
1025     CALL_CALL ("cf::_log_backtrace", G_VOID);
1026     CALL_END;
1027     #endif
1028     }
1029    
1030 root 1.116 /////////////////////////////////////////////////////////////////////////////
1031    
1032 root 1.80 struct EventAPI *watcher_base::GEventAPI;
1033 root 1.116 struct CoroAPI *coroapi::GCoroAPI;
1034 root 1.80
1035 root 1.124 int coroapi::cede_counter;
1036 root 1.189 double (*coroapi::time)();
1037     double coroapi::next_cede;
1038    
1039     void coroapi::do_cede_to_tick ()
1040     {
1041     cede_counter = 0;
1042    
1043     cede ();
1044    
1045     next_cede += (TICK / CEDES_PER_TICK) * 0.99;
1046     if (next_cede > SvNV (sv_next_tick) - 0.02)
1047     next_cede = SvNV (sv_next_tick);
1048     }
1049    
1050     void coroapi::do_cede_every ()
1051     {
1052     cede_counter = 0;
1053    
1054     if (coroapi::nready ())
1055     coroapi::cede ();
1056     }
1057    
1058     void coroapi::do_cede_to_tick_every ()
1059     {
1060     cede_counter = 0;
1061    
1062     cede_to_tick ();
1063     }
1064 root 1.124
1065 root 1.188 void
1066     coroapi::wait_for_tick ()
1067     {
1068     CALL_BEGIN (0);
1069     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1070     CALL_END;
1071     }
1072    
1073     void
1074     coroapi::wait_for_tick_begin ()
1075     {
1076     CALL_BEGIN (0);
1077     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1078     CALL_END;
1079     }
1080    
1081     static void
1082     iw_dispatch (pe_event *ev)
1083 root 1.85 {
1084     iw *w = (iw *)ev->ext_data;
1085     w->call (*w);
1086     }
1087    
1088     void
1089     iw::alloc ()
1090     {
1091     pe = GEventAPI->new_idle (0, 0);
1092    
1093 root 1.150 WaREENTRANT_off (pe);
1094 root 1.85 pe->base.callback = (void *)iw_dispatch;
1095     pe->base.ext_data = (void *)this;
1096     }
1097    
1098 root 1.80 static void iow_dispatch (pe_event *ev)
1099     {
1100     iow *w = (iow *)ev->ext_data;
1101     w->call (*w, ((pe_ioevent *)ev)->got);
1102     }
1103    
1104     void
1105     iow::alloc ()
1106     {
1107     pe = GEventAPI->new_io (0, 0);
1108    
1109 root 1.150 WaREENTRANT_off (pe);
1110 root 1.80 pe->base.callback = (void *)iow_dispatch;
1111     pe->base.ext_data = (void *)this;
1112    
1113 root 1.81 pe->fd = -1;
1114     pe->poll = 0;
1115 root 1.80 }
1116    
1117 root 1.85 void
1118 root 1.80 iow::fd (int fd)
1119     {
1120     pe->fd = fd;
1121     }
1122    
1123     int
1124     iow::poll ()
1125     {
1126     return pe->poll;
1127     }
1128    
1129 root 1.85 void
1130 root 1.80 iow::poll (int events)
1131     {
1132 root 1.81 if (pe->poll != events)
1133     {
1134     if (pe->poll) stop ();
1135     pe->poll = events;
1136     if (pe->poll) start ();
1137     }
1138 root 1.80 }
1139    
1140 root 1.109 void
1141     _connect_to_perl ()
1142     {
1143     stash_cf = gv_stashpv ("cf" , 1);
1144    
1145     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1146     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1147     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1148     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1149     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1150     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1151     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1152     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1153     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1154    
1155 root 1.189 sv_runtime = get_sv ("cf::RUNTIME" , 1); sv_upgrade (sv_runtime , SVt_NV);
1156     sv_next_tick = get_sv ("cf::NEXT_TICK", 1); sv_upgrade (sv_next_tick, SVt_NV);
1157 root 1.116
1158 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1159     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1160     cb_object = get_av ("cf::CB_OBJECT", 1);
1161     cb_player = get_av ("cf::CB_PLAYER", 1);
1162     cb_client = get_av ("cf::CB_CLIENT", 1);
1163     cb_type = get_av ("cf::CB_TYPE" , 1);
1164     cb_map = get_av ("cf::CB_MAP" , 1);
1165     }
1166    
1167 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1168    
1169     BOOT:
1170     {
1171 root 1.116 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1172     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1173 root 1.80
1174 root 1.189 _connect_to_perl ();
1175    
1176 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1177 root 1.63
1178 root 1.189 {
1179     require_pv ("Time::HiRes");
1180    
1181     SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1182     if (!svp) croak ("Time::HiRes is required");
1183     if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1184     coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1185     }
1186    
1187 root 1.1 static const struct {
1188     const char *name;
1189     IV iv;
1190     } *civ, const_iv[] = {
1191     # define const_iv(name) { # name, (IV)name },
1192 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1193 root 1.198 const_iv (logBacktrace)
1194 root 1.180
1195 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1196    
1197     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1198 root 1.180
1199 root 1.5 const_iv (MAX_TIME)
1200 root 1.189
1201 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1202     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1203     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1204     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1205     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1206     const_iv (body_wrist) const_iv (body_waist)
1207 root 1.205
1208 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1209     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1210     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1211     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1212     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1213     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1214     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1215     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1216     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1217     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1218     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1219     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1220     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1221     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1222     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1223     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1224     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1225     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1226     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1227     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1228     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1229     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1230     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1231     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1232     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1233     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1234     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1235     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1236 root 1.1
1237 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1238 root 1.14
1239 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1240     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1241 root 1.1
1242 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1243     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1244     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1245     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1246     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1247     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1248     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1249    
1250     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1251     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1252 root 1.1 const_iv (WEAP_BLUD)
1253    
1254 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1255 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1256 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1257     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1258     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1259     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1260     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1261     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1262     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1263     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1264     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1265     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1266     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1267     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1268     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1269     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1270     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1271     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1272     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1273     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1274     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1275     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1276     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1277     const_iv (FLAG_OBJ_SAVE_ON_OVL) const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1278     const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1279     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1280    
1281     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1282     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1283     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1284     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1285 root 1.1 const_iv (NDI_ALL)
1286    
1287 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1288     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1289    
1290     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1291    
1292 root 1.212 const_iv (SP_RAISE_DEAD)
1293     const_iv (SP_RUNE)
1294     const_iv (SP_MAKE_MARK)
1295     const_iv (SP_BOLT)
1296     const_iv (SP_BULLET)
1297     const_iv (SP_EXPLOSION)
1298     const_iv (SP_CONE)
1299     const_iv (SP_BOMB)
1300     const_iv (SP_WONDER)
1301     const_iv (SP_SMITE)
1302     const_iv (SP_MAGIC_MISSILE)
1303     const_iv (SP_SUMMON_GOLEM)
1304     const_iv (SP_DIMENSION_DOOR)
1305     const_iv (SP_MAGIC_MAPPING)
1306     const_iv (SP_MAGIC_WALL)
1307     const_iv (SP_DESTRUCTION)
1308     const_iv (SP_PERCEIVE_SELF)
1309     const_iv (SP_WORD_OF_RECALL)
1310     const_iv (SP_INVISIBLE)
1311     const_iv (SP_PROBE)
1312     const_iv (SP_HEALING)
1313     const_iv (SP_CREATE_FOOD)
1314     const_iv (SP_EARTH_TO_DUST)
1315     const_iv (SP_CHANGE_ABILITY)
1316     const_iv (SP_BLESS)
1317     const_iv (SP_CURSE)
1318     const_iv (SP_SUMMON_MONSTER)
1319     const_iv (SP_CHARGING)
1320     const_iv (SP_POLYMORPH)
1321     const_iv (SP_ALCHEMY)
1322     const_iv (SP_REMOVE_CURSE)
1323     const_iv (SP_IDENTIFY)
1324     const_iv (SP_DETECTION)
1325     const_iv (SP_MOOD_CHANGE)
1326     const_iv (SP_MOVING_BALL)
1327     const_iv (SP_SWARM)
1328     const_iv (SP_CHANGE_MANA)
1329     const_iv (SP_DISPEL_RUNE)
1330     const_iv (SP_CREATE_MISSILE)
1331     const_iv (SP_CONSECRATE)
1332     const_iv (SP_ANIMATE_WEAPON)
1333     const_iv (SP_LIGHT)
1334     const_iv (SP_CHANGE_MAP_LIGHT)
1335     const_iv (SP_FAERY_FIRE)
1336     const_iv (SP_CAUSE_DISEASE)
1337     const_iv (SP_AURA)
1338     const_iv (SP_TOWN_PORTAL)
1339     const_iv (SP_PARTY_SPELL)
1340    
1341 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1342     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1343 root 1.1 const_iv (F_LOCKED)
1344    
1345 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1346    
1347     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1348     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1349    
1350     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1351    
1352     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1353     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1354    
1355     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1356     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1357    
1358     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1359    
1360     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1361     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1362     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1363     const_iv (M_ICE) const_iv (M_SPECIAL)
1364    
1365     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1366     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1367    
1368     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1369     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1370     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1371     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1372     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1373     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1374     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1375     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1376     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1377     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1378 root 1.1 const_iv (SK_POISON_NAIL)
1379    
1380 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1381     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1382     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1383     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1384     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1385     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1386    
1387     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1388    
1389     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1390     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1391     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1392     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1393     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1394     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1395     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1396    
1397     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1398    
1399     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1400     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1401    
1402     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1403    
1404     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1405 root 1.99
1406 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1407 root 1.117
1408     // random map generator
1409 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1410     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1411    
1412     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1413     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1414     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1415    
1416     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1417     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1418 root 1.195
1419     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1420     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1421     const_iv (GT_MINIMAL)
1422 root 1.1 };
1423    
1424     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1425 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1426 root 1.1
1427     static const struct {
1428     const char *name;
1429 root 1.14 int skip;
1430 root 1.7 IV klass;
1431 root 1.1 IV iv;
1432 root 1.6 } *eiv, event_iv[] = {
1433 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1434 root 1.6 # include "eventinc.h"
1435     # undef def
1436     };
1437    
1438     AV *av = get_av ("cf::EVENT", 1);
1439    
1440     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1441 root 1.7 {
1442     AV *event = newAV ();
1443 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1444 root 1.7 av_push (event, newSViv (eiv->klass));
1445     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1446 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1447 root 1.7 }
1448 root 1.14 }
1449    
1450 root 1.109 void _connect_to_perl ()
1451 root 1.14
1452 root 1.210 void _recalc_want ()
1453    
1454 root 1.47 void _global_reattach ()
1455 root 1.14 CODE:
1456     {
1457     // reattach to all attachable objects in the game.
1458 root 1.128 for_all_clients (ns)
1459     ns->reattach ();
1460 root 1.96
1461 root 1.128 for_all_objects (op)
1462 root 1.109 op->reattach ();
1463 root 1.1 }
1464    
1465 root 1.189 void _post_tick ()
1466     CODE:
1467     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1468    
1469 root 1.192 # support function for map-world.ext
1470     void _quantise (SV *data_sv, SV *plt_sv)
1471     CODE:
1472     {
1473     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1474     croak ("_quantise called with invalid agruments");
1475    
1476     plt_sv = SvRV (plt_sv);
1477     SV **plt = AvARRAY (plt_sv);
1478     int plt_count = AvFILL (plt_sv) + 1;
1479    
1480     STRLEN len;
1481     char *data = SvPVbyte (data_sv, len);
1482     char *dst = data;
1483    
1484     while (len >= 3)
1485     {
1486     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1487     {
1488     char *val = SvPVX (*val_sv);
1489    
1490     if (val [0] == data [0]
1491     && val [1] == data [1]
1492     && val [2] == data [2])
1493     {
1494     *dst++ = val [3];
1495     goto next;
1496     }
1497     }
1498    
1499     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1500     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1501     dst - SvPVX (data_sv), len);
1502    
1503     next:
1504     data += 3;
1505     len -= 3;
1506     }
1507    
1508     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1509     }
1510    
1511 root 1.1 NV floor (NV x)
1512    
1513     NV ceil (NV x)
1514    
1515 root 1.143 NV rndm (...)
1516     CODE:
1517     switch (items)
1518     {
1519     case 0: RETVAL = rndm (); break;
1520     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1521     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1522     default: croak ("cf::rndm requires none, one or two parameters."); break;
1523     }
1524     OUTPUT:
1525     RETVAL
1526    
1527 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1528     CODE:
1529     RETVAL = clamp (value, min_value, max_value);
1530     OUTPUT:
1531     RETVAL
1532    
1533     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1534     CODE:
1535     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1536     OUTPUT:
1537     RETVAL
1538    
1539     void cede_to_tick ()
1540     CODE:
1541     coroapi::cede_to_tick ();
1542    
1543 root 1.5 void server_tick ()
1544 root 1.116 CODE:
1545     runtime = SvNVx (sv_runtime);
1546     server_tick ();
1547 root 1.5
1548 root 1.1 void
1549 root 1.198 log_backtrace (utf8_string msg)
1550    
1551     void
1552     LOG (int flags, utf8_string msg)
1553 root 1.1 PROTOTYPE: $$
1554 root 1.198 C_ARGS: flags, "%s", msg
1555 root 1.1
1556 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1557 root 1.1 PROTOTYPE: $$
1558    
1559 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1560 root 1.1 PROTOTYPE: $$
1561    
1562 root 1.183 const_octet_string
1563     get_maps_directory (octet_string path)
1564 root 1.1 PROTOTYPE: $
1565     ALIAS: maps_directory = 0
1566 root 1.19 CODE:
1567     RETVAL = create_pathname (path);
1568     OUTPUT: RETVAL
1569 root 1.1
1570     void
1571     sub_generation_inc ()
1572     CODE:
1573     PL_sub_generation++;
1574    
1575 root 1.183 const_octet_string
1576 root 1.1 mapdir ()
1577     PROTOTYPE:
1578     ALIAS:
1579     mapdir = 0
1580     uniquedir = 1
1581     tmpdir = 2
1582     confdir = 3
1583     localdir = 4
1584     playerdir = 5
1585     datadir = 6
1586     CODE:
1587 root 1.19 switch (ix)
1588     {
1589     case 0: RETVAL = settings.mapdir ; break;
1590     case 1: RETVAL = settings.uniquedir; break;
1591     case 2: RETVAL = settings.tmpdir ; break;
1592     case 3: RETVAL = settings.confdir ; break;
1593     case 4: RETVAL = settings.localdir ; break;
1594     case 5: RETVAL = settings.playerdir; break;
1595     case 6: RETVAL = settings.datadir ; break;
1596     }
1597 root 1.1 OUTPUT: RETVAL
1598    
1599 root 1.120 void abort ()
1600    
1601 root 1.199 void reset_signals ()
1602    
1603 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1604 root 1.144
1605 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1606 root 1.134
1607 root 1.116 void emergency_save ()
1608    
1609 root 1.156 void _exit (int status = EXIT_SUCCESS)
1610    
1611 root 1.149 UV sv_2watcher (SV *w)
1612     CODE:
1613     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1614     OUTPUT:
1615     RETVAL
1616    
1617 root 1.125 #if _POSIX_MEMLOCK
1618    
1619     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1620    
1621     int munlockall ()
1622    
1623     #endif
1624    
1625 root 1.183 int find_animation (utf8_string text)
1626 root 1.1 PROTOTYPE: $
1627    
1628 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1629 root 1.1
1630 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1631 root 1.1
1632     int
1633     exp_to_level (val64 exp)
1634     CODE:
1635     {
1636     int i = 0;
1637    
1638     RETVAL = settings.max_level;
1639    
1640     for (i = 1; i <= settings.max_level; i++)
1641     {
1642     if (levels[i] > exp)
1643     {
1644     RETVAL = i - 1;
1645     break;
1646     }
1647     }
1648     }
1649     OUTPUT: RETVAL
1650    
1651     val64
1652     level_to_min_exp (int level)
1653     CODE:
1654     if (level > settings.max_level)
1655     RETVAL = levels[settings.max_level];
1656     else if (level < 1)
1657     RETVAL = 0;
1658     else
1659     RETVAL = levels[level];
1660     OUTPUT: RETVAL
1661    
1662     SV *
1663     resistance_to_string (int atnr)
1664     CODE:
1665     if (atnr >= 0 && atnr < NROFATTACKS)
1666     RETVAL = newSVpv (resist_plus[atnr], 0);
1667     else
1668     XSRETURN_UNDEF;
1669     OUTPUT: RETVAL
1670    
1671 root 1.162 bool
1672 root 1.183 load_resource_file (octet_string filename)
1673 root 1.162
1674 root 1.97 MODULE = cf PACKAGE = cf::attachable
1675    
1676 root 1.27 int
1677 root 1.97 valid (SV *obj)
1678 root 1.27 CODE:
1679     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1680     OUTPUT:
1681     RETVAL
1682    
1683 root 1.164 void
1684     debug_trace (attachable *obj, bool on = true)
1685     CODE:
1686     obj->flags &= ~attachable::F_DEBUG_TRACE;
1687     if (on)
1688     obj->flags |= attachable::F_DEBUG_TRACE;
1689    
1690 root 1.153 int mortals_size ()
1691     CODE:
1692     RETVAL = attachable::mortals.size ();
1693     OUTPUT: RETVAL
1694    
1695     #object *mortals (U32 index)
1696     # CODE:
1697     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1698     # OUTPUT: RETVAL
1699    
1700 root 1.173 INCLUDE: $PERL $srcdir/genacc attachable ../include/cfperl.h |
1701 root 1.115
1702 root 1.101 MODULE = cf PACKAGE = cf::global
1703    
1704     int invoke (SV *klass, int event, ...)
1705     CODE:
1706     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1707     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1708     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1709 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1710 root 1.101 OUTPUT: RETVAL
1711    
1712 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1713    
1714 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1715 root 1.62
1716 root 1.18 int invoke (object *op, int event, ...)
1717     CODE:
1718     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1719 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1720     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1721 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1722 root 1.18 OUTPUT: RETVAL
1723    
1724     SV *registry (object *op)
1725    
1726 root 1.134 int objects_size ()
1727     CODE:
1728     RETVAL = objects.size ();
1729     OUTPUT: RETVAL
1730    
1731     object *objects (U32 index)
1732     CODE:
1733     RETVAL = index < objects.size () ? objects [index] : 0;
1734     OUTPUT: RETVAL
1735    
1736     int actives_size ()
1737     CODE:
1738     RETVAL = actives.size ();
1739     OUTPUT: RETVAL
1740    
1741     object *actives (U32 index)
1742 root 1.57 CODE:
1743 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1744 root 1.57 OUTPUT: RETVAL
1745    
1746 root 1.215 const char *slot_use_name (U32 slot)
1747 root 1.205 ALIAS:
1748 root 1.215 slot_nonuse_name = 1
1749 root 1.205 CODE:
1750     {
1751     if (slot >= NUM_BODY_LOCATIONS)
1752     croak ("body slot index out of range");
1753    
1754     switch (ix)
1755     {
1756 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1757     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1758 root 1.205 }
1759     }
1760     OUTPUT:
1761     RETVAL
1762    
1763 root 1.1 # missing properties
1764    
1765 root 1.54 object *head (object *op)
1766     PROTOTYPE: $
1767     CODE:
1768 root 1.134 RETVAL = op->head_ ();
1769 root 1.54 OUTPUT: RETVAL
1770    
1771     int is_head (object *op)
1772     PROTOTYPE: $
1773     CODE:
1774 root 1.134 RETVAL = op->head_ () == op;
1775 root 1.54 OUTPUT: RETVAL
1776    
1777 root 1.1 void
1778     inv (object *obj)
1779     PROTOTYPE: $
1780     PPCODE:
1781     {
1782     object *o;
1783     for (o = obj->inv; o; o = o->below)
1784 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1785 root 1.1 }
1786    
1787 root 1.102 void
1788     set_animation (object *op, int idx)
1789     CODE:
1790     SET_ANIMATION (op, idx);
1791    
1792 elmex 1.160 int
1793     num_animations (object *op)
1794     CODE:
1795     RETVAL = NUM_ANIMATIONS (op);
1796     OUTPUT: RETVAL
1797    
1798 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1799     ALIAS:
1800     slot_used = 1
1801     CODE:
1802     {
1803     if (slot >= NUM_BODY_LOCATIONS)
1804     croak ("body slot index out of range");
1805    
1806 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1807 root 1.205
1808     if (items > 2)
1809     if (ix)
1810 root 1.208 op->slot[slot].used = value;
1811     else
1812 root 1.205 op->slot[slot].info = value;
1813     }
1814     OUTPUT:
1815     RETVAL
1816    
1817 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1818 root 1.58
1819     object *find_marked_object (object *op)
1820    
1821 root 1.109 int need_identify (object *obj);
1822 root 1.1
1823     int apply_shop_mat (object *shop_mat, object *op);
1824    
1825 pippijn 1.172 int move_player (object *op, int dir)
1826     CODE:
1827     RETVAL = move_player (op, dir);
1828     OUTPUT:
1829     RETVAL
1830    
1831 root 1.27 int move (object *op, int dir, object *originator = op)
1832     CODE:
1833     RETVAL = move_ob (op, dir, originator);
1834     OUTPUT:
1835     RETVAL
1836 root 1.1
1837 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1838     CODE:
1839     manual_apply (applied, applier, flags);
1840 root 1.1
1841 root 1.74 void apply_below (object *op)
1842     CODE:
1843     player_apply_below (op);
1844 root 1.1
1845 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1846    
1847 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1848 root 1.1
1849     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1850    
1851 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1852 root 1.1
1853 root 1.116 #//TODO
1854     object *clone_ (object *op, int recursive = 0)
1855 root 1.74 CODE:
1856     if (recursive)
1857     RETVAL = object_create_clone (op);
1858     else
1859     {
1860     RETVAL = object::create ();
1861 root 1.75 op->copy_to (RETVAL);
1862 root 1.74 }
1863     OUTPUT: RETVAL
1864 root 1.1
1865 root 1.74 int pay_item (object *op, object *buyer)
1866     CODE:
1867     RETVAL = pay_for_item (op, buyer);
1868     OUTPUT: RETVAL
1869 root 1.1
1870 root 1.74 int pay_amount (object *op, uint64 amount)
1871     CODE:
1872     RETVAL = pay_for_amount (amount, op);
1873     OUTPUT: RETVAL
1874 root 1.1
1875     void pay_player (object *op, uint64 amount)
1876    
1877 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1878 root 1.1
1879 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1880 root 1.1
1881 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1882     CODE:
1883     do_learn_spell (op, sp, special_prayer);
1884 root 1.1
1885 root 1.74 void forget_spell (object *op, object *sp)
1886     CODE:
1887     do_forget_spell (op, query_name (sp));
1888 root 1.1
1889 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1890 root 1.74 CODE:
1891     RETVAL = check_spell_known (op, spellname);
1892     OUTPUT: RETVAL
1893 root 1.1
1894 root 1.74 int query_money (object *op)
1895 root 1.1 ALIAS: money = 0
1896    
1897 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1898 root 1.1 ALIAS: cost = 0
1899    
1900 root 1.74 void spring_trap (object *op, object *victim)
1901 root 1.1
1902 root 1.74 int check_trigger (object *op, object *cause)
1903 root 1.1
1904 root 1.74 void drop (object *who, object *op)
1905 root 1.1
1906 root 1.74 void pick_up (object *who, object *op)
1907 root 1.1
1908 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
1909 root 1.1
1910 root 1.102 void update_object (object *op, int action)
1911 root 1.1
1912 root 1.183 object *cf_create_object_by_name (utf8_string name)
1913 root 1.1
1914 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
1915 root 1.1
1916     void player_lvl_adj (object *who, object *skill = 0)
1917    
1918     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1919    
1920     int calc_skill_exp (object *who, object *op, object *skill);
1921    
1922     void push_button (object *op);
1923    
1924     void use_trigger (object *op);
1925    
1926 root 1.61 void add_button_link (object *button, maptile *map, int connected);
1927 root 1.1
1928     void remove_button_link (object *op);
1929    
1930    
1931     MODULE = cf PACKAGE = cf::object PREFIX = cf_
1932    
1933     object *cf_insert_ob_in_ob (object *ob, object *where)
1934    
1935     # no clean way to get an object from an archetype - stupid idiotic
1936     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1937    
1938 root 1.183 object *new (utf8_string archetype = 0)
1939 root 1.1 PROTOTYPE: ;$
1940     CODE:
1941     RETVAL = archetype ? get_archetype (archetype) : cf_create_object ();
1942     OUTPUT:
1943     RETVAL
1944    
1945 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1946 root 1.1 PROTOTYPE: $$$$$$
1947     CODE:
1948     {
1949     int unused_type;
1950     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1951     }
1952    
1953     player *contr (object *op)
1954     CODE:
1955     RETVAL = op->contr;
1956     OUTPUT: RETVAL
1957    
1958 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
1959 root 1.1
1960 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
1961 root 1.1
1962     object *get_nearest_player (object *ob)
1963     ALIAS: nearest_player = 0
1964     PREINIT:
1965     extern object *get_nearest_player (object *);
1966    
1967     void rangevector (object *ob, object *other, int flags = 0)
1968     PROTOTYPE: $$;$
1969     PPCODE:
1970     {
1971     rv_vector rv;
1972     get_rangevector (ob, other, &rv, flags);
1973     EXTEND (SP, 5);
1974     PUSHs (newSVuv (rv.distance));
1975     PUSHs (newSViv (rv.distance_x));
1976     PUSHs (newSViv (rv.distance_y));
1977     PUSHs (newSViv (rv.direction));
1978     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
1979     }
1980    
1981     bool on_same_map_as (object *ob, object *other)
1982     CODE:
1983     RETVAL = on_same_map (ob, other);
1984     OUTPUT: RETVAL
1985    
1986 root 1.183 const_utf8_string
1987 root 1.58 base_name (object *op, int plural = op->nrof > 1)
1988 root 1.1 CODE:
1989 root 1.58 RETVAL = query_base_name (op, plural);
1990 root 1.1 OUTPUT: RETVAL
1991    
1992 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
1993    
1994 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
1995    
1996     player *player (object *op)
1997     CODE:
1998     RETVAL = op->contr;
1999     OUTPUT: RETVAL
2000    
2001 root 1.105 void check_score (object *op)
2002    
2003 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2004 root 1.120 CODE:
2005     new_draw_info (flags, 0, op, txt);
2006 root 1.1
2007     void kill_player (object *op)
2008    
2009 root 1.58 void esrv_update_item (object *op, int what, object *item)
2010     C_ARGS: what, op, item
2011    
2012 root 1.66 void clear_los (object *op)
2013    
2014 root 1.183 int command_summon (object *op, utf8_string params)
2015 root 1.67
2016 root 1.183 int command_arrest (object *op, utf8_string params)
2017 root 1.67
2018 root 1.66
2019 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2020 root 1.1
2021 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2022 root 1.62
2023 root 1.18 int invoke (player *pl, int event, ...)
2024     CODE:
2025     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2026 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2027     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2028 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2029 root 1.18 OUTPUT: RETVAL
2030    
2031 root 1.12 SV *registry (player *pl)
2032 root 1.1
2033 root 1.102 void
2034     save_stats (player *pl)
2035     CODE:
2036     pl->ob->stats.hp = pl->ob->stats.maxhp;
2037     pl->ob->stats.sp = pl->ob->stats.maxsp;
2038     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2039     pl->orig_stats = pl->ob->stats;
2040    
2041 root 1.1 void cf_player_move (player *pl, int dir)
2042    
2043     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
2044    
2045     bool
2046     cell_visible (player *pl, int dx, int dy)
2047     CODE:
2048 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2049     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2050 root 1.1 OUTPUT:
2051     RETVAL
2052    
2053 root 1.4 void
2054 root 1.1 send (player *pl, SV *packet)
2055     CODE:
2056     {
2057     STRLEN len;
2058     char *buf = SvPVbyte (packet, len);
2059    
2060 root 1.100 if (pl->ns)
2061     pl->ns->send_packet (buf, len);
2062 root 1.1 }
2063    
2064     int
2065     listening (player *pl, int new_value = -1)
2066     CODE:
2067     RETVAL = pl->listening;
2068     if (new_value >= 0)
2069     pl->listening = new_value;
2070     OUTPUT:
2071     RETVAL
2072    
2073 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2074 root 1.45 PROTOTYPE: $;$$$
2075 root 1.1 PPCODE:
2076 root 1.45 if (GIMME_V != G_VOID)
2077     {
2078     EXTEND (SP, 3);
2079     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2080     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2081     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2082     }
2083 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2084     if (x) sv_to (x, pl->bed_x);
2085     if (y) sv_to (y, pl->bed_y);
2086 root 1.1
2087     void
2088     list ()
2089     PPCODE:
2090 root 1.128 for_all_players (pl)
2091 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2092 root 1.1
2093    
2094     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2095    
2096 root 1.61 int invoke (maptile *map, int event, ...)
2097 root 1.18 CODE:
2098     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2099 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2100     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2101 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2102 root 1.25 OUTPUT: RETVAL
2103 root 1.18
2104 root 1.61 SV *registry (maptile *map)
2105 root 1.12
2106 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2107 root 1.1
2108 root 1.116 void
2109     maptile::instantiate ()
2110    
2111     maptile *new ()
2112 root 1.1 PROTOTYPE:
2113     CODE:
2114 root 1.116 RETVAL = new maptile;
2115 root 1.1 OUTPUT:
2116     RETVAL
2117    
2118 root 1.116 void
2119 root 1.117 maptile::players ()
2120     PPCODE:
2121     if (GIMME_V == G_SCALAR)
2122 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2123 root 1.117 else if (GIMME_V == G_ARRAY)
2124     {
2125     EXTEND (SP, THIS->players);
2126     for_all_players (pl)
2127     if (pl->ob && pl->ob->map == THIS)
2128 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2129 root 1.117 }
2130    
2131 root 1.156 void
2132 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2133 root 1.156 CODE:
2134     {
2135 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2136     croak ("maptile::add_underlay: palette must be arrayref");
2137 root 1.156
2138 root 1.168 palette = SvRV (palette);
2139 root 1.156
2140 root 1.168 STRLEN idxlen;
2141     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2142 root 1.156
2143 root 1.168 for (int x = 0; x < THIS->width; ++x)
2144     for (int y = 0; y < THIS->height; ++y)
2145     {
2146     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2147     if (op->flag [FLAG_IS_FLOOR])
2148     goto skip_space;
2149    
2150     {
2151     int offs = offset + y * stride + x;
2152     if (IN_RANGE_EXC (offs, 0, idxlen))
2153     {
2154     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2155     {
2156     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2157     ob->flag [FLAG_NO_MAP_SAVE] = true;
2158     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2159 root 1.200
2160     if (ob->randomitems)
2161     {
2162 root 1.203 if (!ob->above)
2163     {
2164     ob->create_treasure (ob->randomitems);
2165    
2166     for (object *op = ob->above; op; op = op->above)
2167     op->flag [FLAG_NO_MAP_SAVE] = true;
2168     }
2169    
2170 root 1.200 ob->randomitems = 0;
2171     }
2172 root 1.168 }
2173     }
2174     }
2175 root 1.156
2176 root 1.168 skip_space: ;
2177     }
2178     }
2179    
2180     void
2181     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2182     CODE:
2183     {
2184     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2185     croak ("maptile::set_regiondata: palette must be arrayref");
2186    
2187     palette = SvRV (palette);
2188    
2189     STRLEN idxlen;
2190     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2191    
2192     region **regionmap = (region **)malloc (
2193     (av_len ((AV *)palette) + 1) * sizeof (region *));
2194     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2195    
2196     for (int i = av_len ((AV *)palette) + 1; i--; )
2197     regionmap [i] = region::find (
2198     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2199    
2200     for (int y = 0; y < THIS->height; ++y)
2201     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2202    
2203     sfree (THIS->regions, THIS->size ());
2204     free (THIS->regionmap);
2205    
2206     THIS->regions = regions;
2207 root 1.156 THIS->regionmap = regionmap;
2208     }
2209    
2210 root 1.193 void
2211     maptile::create_region_treasure ()
2212     CODE:
2213     {
2214     object *op = object::create ();
2215     op->type = FLOOR;
2216     op->map = THIS;
2217    
2218     for (int x = 0; x < THIS->width; ++x)
2219     for (int y = 0; y < THIS->height; ++y)
2220     {
2221     region *rgn = THIS->region (x, y);
2222    
2223     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2224     if (rgn->treasure && rndm () < rgn->treasure_density)
2225     {
2226     op->x = x;
2227     op->y = y;
2228     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2229     }
2230     }
2231    
2232     op->destroy ();
2233     }
2234    
2235 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2236 root 1.1
2237 root 1.74 int out_of_map (maptile *map, int x, int y)
2238    
2239 root 1.29 void
2240 root 1.61 trigger (maptile *map, long connection, bool state = true)
2241 root 1.29 CODE:
2242     activate_connection (map, connection, state);
2243    
2244     void
2245 root 1.61 get_connection (maptile *map, long connection)
2246 root 1.29 PPCODE:
2247     oblinkpt *obp = get_connection_links (map, connection);
2248     if (obp)
2249     for (objectlink *ol = obp->link; ol; ol = ol->next)
2250 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2251 root 1.29
2252 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2253 root 1.1
2254 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2255 root 1.1
2256 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2257 root 1.1 C_ARGS: str, map, nx, ny
2258    
2259     void
2260 root 1.140 get_map_flags (maptile *map, int x, int y)
2261 root 1.1 PPCODE:
2262     {
2263 root 1.61 maptile *nmap = 0;
2264 root 1.1 I16 nx = 0, ny = 0;
2265 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2266 root 1.1
2267     EXTEND (SP, 4);
2268     PUSHs (sv_2mortal (newSViv (flags)));
2269    
2270     if (GIMME_V == G_ARRAY)
2271     {
2272     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2273     PUSHs (sv_2mortal (newSViv (nx)));
2274     PUSHs (sv_2mortal (newSViv (ny)));
2275     }
2276     }
2277    
2278     void
2279 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2280 root 1.1 PROTOTYPE: $$$
2281     PPCODE:
2282     {
2283     object *o;
2284 root 1.61 maptile *nmap = 0;
2285 root 1.1 I16 nx, ny;
2286    
2287 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2288 root 1.1
2289     if (nmap)
2290     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2291     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2292     }
2293    
2294     SV *
2295 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2296 root 1.1 PROTOTYPE: $$$
2297     ALIAS:
2298     top_at = 1
2299     flags_at = 2
2300     light_at = 3
2301     move_block_at = 4
2302     move_slow_at = 5
2303     move_on_at = 6
2304     move_off_at = 7
2305     INIT:
2306 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2307 root 1.1 CODE:
2308     switch (ix)
2309     {
2310     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2311     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2312     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2313     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2314     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2315     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2316     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2317     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2318     }
2319 root 1.122 OUTPUT: RETVAL
2320 root 1.1
2321 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2322    
2323     void fix_walls_around (maptile *map, int x, int y)
2324 root 1.1
2325 root 1.117 # worst xs function of my life
2326 root 1.140 bool
2327 root 1.117 _create_random_map (\
2328 root 1.140 maptile *self,\
2329 root 1.183 utf8_string wallstyle,\
2330     utf8_string wall_name,\
2331     utf8_string floorstyle,\
2332     utf8_string monsterstyle,\
2333     utf8_string treasurestyle,\
2334     utf8_string layoutstyle,\
2335     utf8_string doorstyle,\
2336     utf8_string decorstyle,\
2337     utf8_string origin_map,\
2338     utf8_string final_map,\
2339     utf8_string exitstyle,\
2340     utf8_string this_map,\
2341     utf8_string exit_on_final_map,\
2342 root 1.146 int xsize,\
2343     int ysize,\
2344 root 1.117 int expand2x,\
2345     int layoutoptions1,\
2346     int layoutoptions2,\
2347     int layoutoptions3,\
2348     int symmetry,\
2349     int difficulty,\
2350     int difficulty_given,\
2351     float difficulty_increase,\
2352     int dungeon_level,\
2353     int dungeon_depth,\
2354     int decoroptions,\
2355     int orientation,\
2356     int origin_y,\
2357     int origin_x,\
2358 root 1.146 U32 random_seed,\
2359 root 1.117 val64 total_map_hp,\
2360     int map_layout_style,\
2361     int treasureoptions,\
2362     int symmetry_used,\
2363 root 1.137 region *region,\
2364 root 1.183 utf8_string custom\
2365 root 1.117 )
2366     CODE:
2367     {
2368     random_map_params rmp;
2369    
2370     assign (rmp.wallstyle , wallstyle);
2371     assign (rmp.wall_name , wall_name);
2372     assign (rmp.floorstyle , floorstyle);
2373     assign (rmp.monsterstyle , monsterstyle);
2374     assign (rmp.treasurestyle , treasurestyle);
2375     assign (rmp.layoutstyle , layoutstyle);
2376     assign (rmp.doorstyle , doorstyle);
2377     assign (rmp.decorstyle , decorstyle);
2378     assign (rmp.exitstyle , exitstyle);
2379     assign (rmp.exit_on_final_map, exit_on_final_map);
2380    
2381 root 1.122 rmp.origin_map = origin_map;
2382     rmp.final_map = final_map;
2383     rmp.this_map = this_map;
2384 root 1.146 rmp.xsize = xsize;
2385     rmp.ysize = ysize;
2386 root 1.117 rmp.expand2x = expand2x;
2387     rmp.layoutoptions1 = layoutoptions1;
2388     rmp.layoutoptions2 = layoutoptions2;
2389     rmp.layoutoptions3 = layoutoptions3;
2390     rmp.symmetry = symmetry;
2391     rmp.difficulty = difficulty;
2392     rmp.difficulty_given = difficulty_given;
2393     rmp.difficulty_increase = difficulty_increase;
2394     rmp.dungeon_level = dungeon_level;
2395     rmp.dungeon_depth = dungeon_depth;
2396     rmp.decoroptions = decoroptions;
2397     rmp.orientation = orientation;
2398     rmp.origin_y = origin_y;
2399     rmp.origin_x = origin_x;
2400     rmp.random_seed = random_seed;
2401 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2402 root 1.117 rmp.map_layout_style = map_layout_style;
2403     rmp.treasureoptions = treasureoptions;
2404     rmp.symmetry_used = symmetry_used;
2405     rmp.region = region;
2406 root 1.137 rmp.custom = custom;
2407 root 1.117
2408 root 1.140 RETVAL = self->generate_random_map (&rmp);
2409 root 1.117 }
2410     OUTPUT:
2411     RETVAL
2412    
2413 root 1.19 MODULE = cf PACKAGE = cf::arch
2414 root 1.1
2415 root 1.183 archetype *find (utf8_string name)
2416 elmex 1.36 CODE:
2417 root 1.60 RETVAL = archetype::find (name);
2418 elmex 1.36 OUTPUT:
2419     RETVAL
2420    
2421 root 1.19 archetype *first()
2422 root 1.1 PROTOTYPE:
2423 root 1.19 CODE:
2424     RETVAL = first_archetype;
2425     OUTPUT: RETVAL
2426 root 1.1
2427 root 1.212 object *instantiate (archetype *arch)
2428     CODE:
2429     RETVAL = arch_to_object (arch);
2430     OUTPUT:
2431     RETVAL
2432    
2433 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2434 root 1.1
2435 root 1.19 MODULE = cf PACKAGE = cf::party
2436 root 1.1
2437 root 1.19 partylist *first ()
2438 root 1.1 PROTOTYPE:
2439 root 1.19 CODE:
2440     RETVAL = get_firstparty ();
2441     OUTPUT: RETVAL
2442 root 1.1
2443 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2444 root 1.1
2445 root 1.19 MODULE = cf PACKAGE = cf::region
2446 root 1.1
2447 root 1.161 void
2448     list ()
2449     PPCODE:
2450     for_all_regions (rgn)
2451     XPUSHs (sv_2mortal (to_sv (rgn)));
2452    
2453 root 1.183 region *find (utf8_string name)
2454 root 1.161 PROTOTYPE: $
2455 root 1.19 CODE:
2456 root 1.161 RETVAL = region::find (name);
2457 root 1.19 OUTPUT: RETVAL
2458 root 1.1
2459 root 1.183 region *find_fuzzy (utf8_string name)
2460 root 1.122 PROTOTYPE: $
2461     CODE:
2462 root 1.161 RETVAL = region::find_fuzzy (name);
2463 root 1.122 OUTPUT: RETVAL
2464    
2465 root 1.186 int specificity (region *rgn)
2466     CODE:
2467     RETVAL = 0;
2468     while (rgn = rgn->parent)
2469     RETVAL++;
2470     OUTPUT: RETVAL
2471    
2472 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2473 root 1.1
2474 root 1.19 MODULE = cf PACKAGE = cf::living
2475 root 1.1
2476 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2477 root 1.1
2478 root 1.76 MODULE = cf PACKAGE = cf::settings
2479    
2480 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2481 root 1.76
2482 root 1.84 MODULE = cf PACKAGE = cf::client
2483 root 1.79
2484 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2485 root 1.79
2486 root 1.84 int invoke (client *ns, int event, ...)
2487 root 1.79 CODE:
2488 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2489 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2490     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2491 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2492 root 1.79 OUTPUT: RETVAL
2493    
2494 root 1.84 SV *registry (client *ns)
2495 root 1.79
2496 root 1.100 void
2497     list ()
2498     PPCODE:
2499     EXTEND (SP, clients.size ());
2500     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2501     PUSHs (sv_2mortal (to_sv (*i)));
2502    
2503 root 1.88 void
2504 root 1.100 client::send_packet (SV *packet)
2505     CODE:
2506     {
2507     STRLEN len;
2508     char *buf = SvPVbyte (packet, len);
2509    
2510     THIS->send_packet (buf, len);
2511     }
2512    
2513 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2514    
2515 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2516 root 1.176
2517 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2518 root 1.176
2519 root 1.183 faceidx alloc (utf8_string name)
2520 root 1.176 CODE:
2521     {
2522     do
2523     {
2524     RETVAL = faces.size ();
2525 root 1.177 faces.resize (RETVAL + 1);
2526 root 1.176 }
2527     while (!RETVAL); // crude way to leave index 0
2528    
2529     faces [RETVAL].name = name;
2530     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2531    
2532     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2533     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2534     }
2535     OUTPUT: RETVAL
2536    
2537 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2538 root 1.176 CODE:
2539 root 1.177 faceinfo *f = face_info (idx);
2540     assert (f);
2541     f->visibility = visibility;
2542     f->magicmap = magicmap;
2543 root 1.176
2544 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2545 root 1.177 CODE:
2546 root 1.184 faceinfo *f = face_info (idx); assert (f);
2547     f->smooth = smooth;
2548     f->smoothlevel = smoothlevel;
2549 root 1.177
2550     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2551 root 1.176 CODE:
2552 root 1.182 {
2553 root 1.176 facedata *d = face_data (idx, faceset);
2554 root 1.177 assert (d);
2555 root 1.181 sv_to (data, d->data);
2556     STRLEN clen;
2557     char *cdata = SvPVbyte (chksum, clen);
2558 root 1.182 clen = min (CHKSUM_SIZE, clen);
2559    
2560     if (memcmp (d->chksum, cdata, clen))
2561     {
2562     memcpy (d->chksum, cdata, clen);
2563    
2564     // invalidate existing client face info
2565     for_all_clients (ns)
2566     if (ns->faceset == faceset)
2567     {
2568     ns->faces_sent [idx] = false;
2569     ns->force_newmap = true;
2570     }
2571     }
2572     }
2573 root 1.176
2574 root 1.177 void invalidate (faceidx idx)
2575     CODE:
2576     for_all_clients (ns)
2577 root 1.182 {
2578     ns->faces_sent [idx] = false;
2579     ns->force_newmap = true;
2580     }
2581 root 1.177
2582     void invalidate_all ()
2583     CODE:
2584     for_all_clients (ns)
2585 root 1.182 {
2586     ns->faces_sent.reset ();
2587     ns->force_newmap = true;
2588     }
2589 root 1.177
2590 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2591    
2592     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2593    
2594     animidx anim_find (utf8_string name)
2595     CODE:
2596     RETVAL = animation::find (name).number;
2597     OUTPUT: RETVAL
2598    
2599     animidx set (utf8_string name, SV *frames, int facings = 1)
2600     CODE:
2601     {
2602     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2603     croak ("frames must be an arrayref");
2604    
2605     AV *av = (AV *)SvRV (frames);
2606    
2607     animation *anim = &animation::find (name);
2608     if (anim->number)
2609     {
2610     anim->resize (av_len (av) + 1);
2611     anim->facings = facings;
2612     }
2613     else
2614     anim = &animation::create (name, av_len (av) + 1, facings);
2615    
2616     for (int i = 0; i < anim->num_animations; ++i)
2617     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2618     }
2619     OUTPUT: RETVAL
2620    
2621     void invalidate_all ()
2622     CODE:
2623     for_all_clients (ns)
2624     ns->anims_sent.reset ();
2625