ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.212
Committed: Tue May 22 10:50:01 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.211: +55 -0 lines
Log Message:
- fix players frozen on movers
- allow overriding of existing spells

implement town portal:
- new fields portasl_maap|x|y for regions
- new ext town_portsla completelyx implementing it
- some debugging code, some check code

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 root 1.212 const_iv (SP_RAISE_DEAD)
1280     const_iv (SP_RUNE)
1281     const_iv (SP_MAKE_MARK)
1282     const_iv (SP_BOLT)
1283     const_iv (SP_BULLET)
1284     const_iv (SP_EXPLOSION)
1285     const_iv (SP_CONE)
1286     const_iv (SP_BOMB)
1287     const_iv (SP_WONDER)
1288     const_iv (SP_SMITE)
1289     const_iv (SP_MAGIC_MISSILE)
1290     const_iv (SP_SUMMON_GOLEM)
1291     const_iv (SP_DIMENSION_DOOR)
1292     const_iv (SP_MAGIC_MAPPING)
1293     const_iv (SP_MAGIC_WALL)
1294     const_iv (SP_DESTRUCTION)
1295     const_iv (SP_PERCEIVE_SELF)
1296     const_iv (SP_WORD_OF_RECALL)
1297     const_iv (SP_INVISIBLE)
1298     const_iv (SP_PROBE)
1299     const_iv (SP_HEALING)
1300     const_iv (SP_CREATE_FOOD)
1301     const_iv (SP_EARTH_TO_DUST)
1302     const_iv (SP_CHANGE_ABILITY)
1303     const_iv (SP_BLESS)
1304     const_iv (SP_CURSE)
1305     const_iv (SP_SUMMON_MONSTER)
1306     const_iv (SP_CHARGING)
1307     const_iv (SP_POLYMORPH)
1308     const_iv (SP_ALCHEMY)
1309     const_iv (SP_REMOVE_CURSE)
1310     const_iv (SP_IDENTIFY)
1311     const_iv (SP_DETECTION)
1312     const_iv (SP_MOOD_CHANGE)
1313     const_iv (SP_MOVING_BALL)
1314     const_iv (SP_SWARM)
1315     const_iv (SP_CHANGE_MANA)
1316     const_iv (SP_DISPEL_RUNE)
1317     const_iv (SP_CREATE_MISSILE)
1318     const_iv (SP_CONSECRATE)
1319     const_iv (SP_ANIMATE_WEAPON)
1320     const_iv (SP_LIGHT)
1321     const_iv (SP_CHANGE_MAP_LIGHT)
1322     const_iv (SP_FAERY_FIRE)
1323     const_iv (SP_CAUSE_DISEASE)
1324     const_iv (SP_AURA)
1325     const_iv (SP_TOWN_PORTAL)
1326     const_iv (SP_PARTY_SPELL)
1327    
1328 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1329     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1330 root 1.1 const_iv (F_LOCKED)
1331    
1332 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1333    
1334     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1335     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1336    
1337     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1338    
1339     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1340     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1341    
1342     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1343     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1344    
1345     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1346    
1347     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1348     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1349     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1350     const_iv (M_ICE) const_iv (M_SPECIAL)
1351    
1352     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1353     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1354    
1355     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1356     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1357     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1358     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1359     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1360     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1361     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1362     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1363     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1364     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1365 root 1.1 const_iv (SK_POISON_NAIL)
1366    
1367 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1368     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1369     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1370     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1371     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1372     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1373    
1374     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1375    
1376     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1377     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1378     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1379     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1380     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1381     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1382     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1383    
1384     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1385    
1386     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1387     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1388    
1389     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1390    
1391     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1392 root 1.99
1393 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1394 root 1.117
1395     // random map generator
1396 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1397     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1398    
1399     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1400     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1401     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1402    
1403     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1404     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1405 root 1.195
1406     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1407     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1408     const_iv (GT_MINIMAL)
1409 root 1.1 };
1410    
1411     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1412 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1413 root 1.1
1414     static const struct {
1415     const char *name;
1416 root 1.14 int skip;
1417 root 1.7 IV klass;
1418 root 1.1 IV iv;
1419 root 1.6 } *eiv, event_iv[] = {
1420 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1421 root 1.6 # include "eventinc.h"
1422     # undef def
1423     };
1424    
1425     AV *av = get_av ("cf::EVENT", 1);
1426    
1427     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1428 root 1.7 {
1429     AV *event = newAV ();
1430 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1431 root 1.7 av_push (event, newSViv (eiv->klass));
1432     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1433 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1434 root 1.7 }
1435 root 1.14 }
1436    
1437 root 1.109 void _connect_to_perl ()
1438 root 1.14
1439 root 1.210 void _recalc_want ()
1440    
1441 root 1.47 void _global_reattach ()
1442 root 1.14 CODE:
1443     {
1444     // reattach to all attachable objects in the game.
1445 root 1.128 for_all_clients (ns)
1446     ns->reattach ();
1447 root 1.96
1448 root 1.128 for_all_objects (op)
1449 root 1.109 op->reattach ();
1450 root 1.1 }
1451    
1452 root 1.189 void _post_tick ()
1453     CODE:
1454     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1455    
1456 root 1.192 # support function for map-world.ext
1457     void _quantise (SV *data_sv, SV *plt_sv)
1458     CODE:
1459     {
1460     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1461     croak ("_quantise called with invalid agruments");
1462    
1463     plt_sv = SvRV (plt_sv);
1464     SV **plt = AvARRAY (plt_sv);
1465     int plt_count = AvFILL (plt_sv) + 1;
1466    
1467     STRLEN len;
1468     char *data = SvPVbyte (data_sv, len);
1469     char *dst = data;
1470    
1471     while (len >= 3)
1472     {
1473     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1474     {
1475     char *val = SvPVX (*val_sv);
1476    
1477     if (val [0] == data [0]
1478     && val [1] == data [1]
1479     && val [2] == data [2])
1480     {
1481     *dst++ = val [3];
1482     goto next;
1483     }
1484     }
1485    
1486     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1487     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1488     dst - SvPVX (data_sv), len);
1489    
1490     next:
1491     data += 3;
1492     len -= 3;
1493     }
1494    
1495     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1496     }
1497    
1498 root 1.1 NV floor (NV x)
1499    
1500     NV ceil (NV x)
1501    
1502 root 1.143 NV rndm (...)
1503     CODE:
1504     switch (items)
1505     {
1506     case 0: RETVAL = rndm (); break;
1507     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1508     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1509     default: croak ("cf::rndm requires none, one or two parameters."); break;
1510     }
1511     OUTPUT:
1512     RETVAL
1513    
1514 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1515     CODE:
1516     RETVAL = clamp (value, min_value, max_value);
1517     OUTPUT:
1518     RETVAL
1519    
1520     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1521     CODE:
1522     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1523     OUTPUT:
1524     RETVAL
1525    
1526     void cede_to_tick ()
1527     CODE:
1528     coroapi::cede_to_tick ();
1529    
1530 root 1.5 void server_tick ()
1531 root 1.116 CODE:
1532     runtime = SvNVx (sv_runtime);
1533     server_tick ();
1534 root 1.5
1535 root 1.1 void
1536 root 1.198 log_backtrace (utf8_string msg)
1537    
1538     void
1539     LOG (int flags, utf8_string msg)
1540 root 1.1 PROTOTYPE: $$
1541 root 1.198 C_ARGS: flags, "%s", msg
1542 root 1.1
1543 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1544 root 1.1 PROTOTYPE: $$
1545    
1546 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1547 root 1.1 PROTOTYPE: $$
1548    
1549 root 1.183 const_octet_string
1550     get_maps_directory (octet_string path)
1551 root 1.1 PROTOTYPE: $
1552     ALIAS: maps_directory = 0
1553 root 1.19 CODE:
1554     RETVAL = create_pathname (path);
1555     OUTPUT: RETVAL
1556 root 1.1
1557     void
1558     sub_generation_inc ()
1559     CODE:
1560     PL_sub_generation++;
1561    
1562 root 1.183 const_octet_string
1563 root 1.1 mapdir ()
1564     PROTOTYPE:
1565     ALIAS:
1566     mapdir = 0
1567     uniquedir = 1
1568     tmpdir = 2
1569     confdir = 3
1570     localdir = 4
1571     playerdir = 5
1572     datadir = 6
1573     CODE:
1574 root 1.19 switch (ix)
1575     {
1576     case 0: RETVAL = settings.mapdir ; break;
1577     case 1: RETVAL = settings.uniquedir; break;
1578     case 2: RETVAL = settings.tmpdir ; break;
1579     case 3: RETVAL = settings.confdir ; break;
1580     case 4: RETVAL = settings.localdir ; break;
1581     case 5: RETVAL = settings.playerdir; break;
1582     case 6: RETVAL = settings.datadir ; break;
1583     }
1584 root 1.1 OUTPUT: RETVAL
1585    
1586 root 1.120 void abort ()
1587    
1588 root 1.199 void reset_signals ()
1589    
1590 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1591 root 1.144
1592 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1593 root 1.134
1594 root 1.116 void emergency_save ()
1595    
1596 root 1.156 void _exit (int status = EXIT_SUCCESS)
1597    
1598 root 1.149 UV sv_2watcher (SV *w)
1599     CODE:
1600     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1601     OUTPUT:
1602     RETVAL
1603    
1604 root 1.125 #if _POSIX_MEMLOCK
1605    
1606     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1607    
1608     int munlockall ()
1609    
1610     #endif
1611    
1612 root 1.183 int find_animation (utf8_string text)
1613 root 1.1 PROTOTYPE: $
1614    
1615 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1616 root 1.1
1617 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1618 root 1.1
1619     int
1620     exp_to_level (val64 exp)
1621     CODE:
1622     {
1623     int i = 0;
1624    
1625     RETVAL = settings.max_level;
1626    
1627     for (i = 1; i <= settings.max_level; i++)
1628     {
1629     if (levels[i] > exp)
1630     {
1631     RETVAL = i - 1;
1632     break;
1633     }
1634     }
1635     }
1636     OUTPUT: RETVAL
1637    
1638     val64
1639     level_to_min_exp (int level)
1640     CODE:
1641     if (level > settings.max_level)
1642     RETVAL = levels[settings.max_level];
1643     else if (level < 1)
1644     RETVAL = 0;
1645     else
1646     RETVAL = levels[level];
1647     OUTPUT: RETVAL
1648    
1649     SV *
1650     resistance_to_string (int atnr)
1651     CODE:
1652     if (atnr >= 0 && atnr < NROFATTACKS)
1653     RETVAL = newSVpv (resist_plus[atnr], 0);
1654     else
1655     XSRETURN_UNDEF;
1656     OUTPUT: RETVAL
1657    
1658 root 1.162 bool
1659 root 1.183 load_resource_file (octet_string filename)
1660 root 1.162
1661 root 1.97 MODULE = cf PACKAGE = cf::attachable
1662    
1663 root 1.27 int
1664 root 1.97 valid (SV *obj)
1665 root 1.27 CODE:
1666     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1667     OUTPUT:
1668     RETVAL
1669    
1670 root 1.164 void
1671     debug_trace (attachable *obj, bool on = true)
1672     CODE:
1673     obj->flags &= ~attachable::F_DEBUG_TRACE;
1674     if (on)
1675     obj->flags |= attachable::F_DEBUG_TRACE;
1676    
1677 root 1.153 int mortals_size ()
1678     CODE:
1679     RETVAL = attachable::mortals.size ();
1680     OUTPUT: RETVAL
1681    
1682     #object *mortals (U32 index)
1683     # CODE:
1684     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1685     # OUTPUT: RETVAL
1686    
1687 root 1.173 INCLUDE: $PERL $srcdir/genacc attachable ../include/cfperl.h |
1688 root 1.115
1689 root 1.101 MODULE = cf PACKAGE = cf::global
1690    
1691     int invoke (SV *klass, int event, ...)
1692     CODE:
1693     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1694     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1695     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1696 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1697 root 1.101 OUTPUT: RETVAL
1698    
1699 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1700    
1701 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1702 root 1.62
1703 root 1.18 int invoke (object *op, int event, ...)
1704     CODE:
1705     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1706 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1707     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1708 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1709 root 1.18 OUTPUT: RETVAL
1710    
1711     SV *registry (object *op)
1712    
1713 root 1.134 int objects_size ()
1714     CODE:
1715     RETVAL = objects.size ();
1716     OUTPUT: RETVAL
1717    
1718     object *objects (U32 index)
1719     CODE:
1720     RETVAL = index < objects.size () ? objects [index] : 0;
1721     OUTPUT: RETVAL
1722    
1723     int actives_size ()
1724     CODE:
1725     RETVAL = actives.size ();
1726     OUTPUT: RETVAL
1727    
1728     object *actives (U32 index)
1729 root 1.57 CODE:
1730 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1731 root 1.57 OUTPUT: RETVAL
1732    
1733 root 1.205 const char *slot_save_name (U32 slot)
1734     ALIAS:
1735     slot_use_name = 1
1736     slot_nonuse_name = 2
1737     CODE:
1738     {
1739     if (slot >= NUM_BODY_LOCATIONS)
1740     croak ("body slot index out of range");
1741    
1742     switch (ix)
1743     {
1744     case 0: RETVAL = body_locations[slot].save_name; break;
1745     case 1: RETVAL = body_locations[slot].use_name; break;
1746     case 2: RETVAL = body_locations[slot].nonuse_name; break;
1747     }
1748     }
1749     OUTPUT:
1750     RETVAL
1751    
1752 root 1.1 # missing properties
1753    
1754 root 1.54 object *head (object *op)
1755     PROTOTYPE: $
1756     CODE:
1757 root 1.134 RETVAL = op->head_ ();
1758 root 1.54 OUTPUT: RETVAL
1759    
1760     int is_head (object *op)
1761     PROTOTYPE: $
1762     CODE:
1763 root 1.134 RETVAL = op->head_ () == op;
1764 root 1.54 OUTPUT: RETVAL
1765    
1766 root 1.1 void
1767     inv (object *obj)
1768     PROTOTYPE: $
1769     PPCODE:
1770     {
1771     object *o;
1772     for (o = obj->inv; o; o = o->below)
1773 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1774 root 1.1 }
1775    
1776 root 1.102 void
1777     set_animation (object *op, int idx)
1778     CODE:
1779     SET_ANIMATION (op, idx);
1780    
1781 elmex 1.160 int
1782     num_animations (object *op)
1783     CODE:
1784     RETVAL = NUM_ANIMATIONS (op);
1785     OUTPUT: RETVAL
1786    
1787 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1788     ALIAS:
1789     slot_used = 1
1790     CODE:
1791     {
1792     if (slot >= NUM_BODY_LOCATIONS)
1793     croak ("body slot index out of range");
1794    
1795 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1796 root 1.205
1797     if (items > 2)
1798     if (ix)
1799 root 1.208 op->slot[slot].used = value;
1800     else
1801 root 1.205 op->slot[slot].info = value;
1802     }
1803     OUTPUT:
1804     RETVAL
1805    
1806 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1807 root 1.58
1808     object *find_marked_object (object *op)
1809    
1810 root 1.109 int need_identify (object *obj);
1811 root 1.1
1812     int apply_shop_mat (object *shop_mat, object *op);
1813    
1814 pippijn 1.172 int move_player (object *op, int dir)
1815     CODE:
1816     RETVAL = move_player (op, dir);
1817     OUTPUT:
1818     RETVAL
1819    
1820 root 1.27 int move (object *op, int dir, object *originator = op)
1821     CODE:
1822     RETVAL = move_ob (op, dir, originator);
1823     OUTPUT:
1824     RETVAL
1825 root 1.1
1826 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1827     CODE:
1828     manual_apply (applied, applier, flags);
1829 root 1.1
1830 root 1.74 void apply_below (object *op)
1831     CODE:
1832     player_apply_below (op);
1833 root 1.1
1834 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1835    
1836 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1837 root 1.1
1838     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1839    
1840 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1841 root 1.1
1842 root 1.116 #//TODO
1843     object *clone_ (object *op, int recursive = 0)
1844 root 1.74 CODE:
1845     if (recursive)
1846     RETVAL = object_create_clone (op);
1847     else
1848     {
1849     RETVAL = object::create ();
1850 root 1.75 op->copy_to (RETVAL);
1851 root 1.74 }
1852     OUTPUT: RETVAL
1853 root 1.1
1854 root 1.74 int pay_item (object *op, object *buyer)
1855     CODE:
1856     RETVAL = pay_for_item (op, buyer);
1857     OUTPUT: RETVAL
1858 root 1.1
1859 root 1.74 int pay_amount (object *op, uint64 amount)
1860     CODE:
1861     RETVAL = pay_for_amount (amount, op);
1862     OUTPUT: RETVAL
1863 root 1.1
1864     void pay_player (object *op, uint64 amount)
1865    
1866 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1867 root 1.1
1868 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1869 root 1.1
1870 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1871     CODE:
1872     do_learn_spell (op, sp, special_prayer);
1873 root 1.1
1874 root 1.74 void forget_spell (object *op, object *sp)
1875     CODE:
1876     do_forget_spell (op, query_name (sp));
1877 root 1.1
1878 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1879 root 1.74 CODE:
1880     RETVAL = check_spell_known (op, spellname);
1881     OUTPUT: RETVAL
1882 root 1.1
1883 root 1.74 int query_money (object *op)
1884 root 1.1 ALIAS: money = 0
1885    
1886 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1887 root 1.1 ALIAS: cost = 0
1888    
1889 root 1.74 void spring_trap (object *op, object *victim)
1890 root 1.1
1891 root 1.74 int check_trigger (object *op, object *cause)
1892 root 1.1
1893 root 1.74 void drop (object *who, object *op)
1894 root 1.1
1895 root 1.74 void pick_up (object *who, object *op)
1896 root 1.1
1897 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
1898 root 1.1
1899 root 1.102 void update_object (object *op, int action)
1900 root 1.1
1901 root 1.183 object *cf_create_object_by_name (utf8_string name)
1902 root 1.1
1903 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
1904 root 1.1
1905     void player_lvl_adj (object *who, object *skill = 0)
1906    
1907     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1908    
1909     int calc_skill_exp (object *who, object *op, object *skill);
1910    
1911     void push_button (object *op);
1912    
1913     void use_trigger (object *op);
1914    
1915 root 1.61 void add_button_link (object *button, maptile *map, int connected);
1916 root 1.1
1917     void remove_button_link (object *op);
1918    
1919    
1920     MODULE = cf PACKAGE = cf::object PREFIX = cf_
1921    
1922     object *cf_insert_ob_in_ob (object *ob, object *where)
1923    
1924     # no clean way to get an object from an archetype - stupid idiotic
1925     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1926    
1927 root 1.183 object *new (utf8_string archetype = 0)
1928 root 1.1 PROTOTYPE: ;$
1929     CODE:
1930     RETVAL = archetype ? get_archetype (archetype) : cf_create_object ();
1931     OUTPUT:
1932     RETVAL
1933    
1934 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1935 root 1.1 PROTOTYPE: $$$$$$
1936     CODE:
1937     {
1938     int unused_type;
1939     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1940     }
1941    
1942     player *contr (object *op)
1943     CODE:
1944     RETVAL = op->contr;
1945     OUTPUT: RETVAL
1946    
1947 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
1948 root 1.1
1949 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
1950 root 1.1
1951     object *get_nearest_player (object *ob)
1952     ALIAS: nearest_player = 0
1953     PREINIT:
1954     extern object *get_nearest_player (object *);
1955    
1956     void rangevector (object *ob, object *other, int flags = 0)
1957     PROTOTYPE: $$;$
1958     PPCODE:
1959     {
1960     rv_vector rv;
1961     get_rangevector (ob, other, &rv, flags);
1962     EXTEND (SP, 5);
1963     PUSHs (newSVuv (rv.distance));
1964     PUSHs (newSViv (rv.distance_x));
1965     PUSHs (newSViv (rv.distance_y));
1966     PUSHs (newSViv (rv.direction));
1967     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
1968     }
1969    
1970     bool on_same_map_as (object *ob, object *other)
1971     CODE:
1972     RETVAL = on_same_map (ob, other);
1973     OUTPUT: RETVAL
1974    
1975 root 1.183 const_utf8_string
1976 root 1.58 base_name (object *op, int plural = op->nrof > 1)
1977 root 1.1 CODE:
1978 root 1.58 RETVAL = query_base_name (op, plural);
1979 root 1.1 OUTPUT: RETVAL
1980    
1981 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
1982    
1983 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
1984    
1985     player *player (object *op)
1986     CODE:
1987     RETVAL = op->contr;
1988     OUTPUT: RETVAL
1989    
1990 root 1.105 void check_score (object *op)
1991    
1992 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
1993 root 1.120 CODE:
1994     new_draw_info (flags, 0, op, txt);
1995 root 1.1
1996     void kill_player (object *op)
1997    
1998 root 1.58 void esrv_update_item (object *op, int what, object *item)
1999     C_ARGS: what, op, item
2000    
2001 root 1.66 void clear_los (object *op)
2002    
2003 root 1.183 int command_summon (object *op, utf8_string params)
2004 root 1.67
2005 root 1.183 int command_arrest (object *op, utf8_string params)
2006 root 1.67
2007 root 1.66
2008 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2009 root 1.1
2010 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2011 root 1.62
2012 root 1.18 int invoke (player *pl, int event, ...)
2013     CODE:
2014     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2015 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2016     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2017 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2018 root 1.18 OUTPUT: RETVAL
2019    
2020 root 1.12 SV *registry (player *pl)
2021 root 1.1
2022 root 1.102 void
2023     save_stats (player *pl)
2024     CODE:
2025     pl->ob->stats.hp = pl->ob->stats.maxhp;
2026     pl->ob->stats.sp = pl->ob->stats.maxsp;
2027     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2028     pl->orig_stats = pl->ob->stats;
2029    
2030 root 1.1 void cf_player_move (player *pl, int dir)
2031    
2032     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
2033    
2034     bool
2035     cell_visible (player *pl, int dx, int dy)
2036     CODE:
2037 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2038     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2039 root 1.1 OUTPUT:
2040     RETVAL
2041    
2042 root 1.4 void
2043 root 1.1 send (player *pl, SV *packet)
2044     CODE:
2045     {
2046     STRLEN len;
2047     char *buf = SvPVbyte (packet, len);
2048    
2049 root 1.100 if (pl->ns)
2050     pl->ns->send_packet (buf, len);
2051 root 1.1 }
2052    
2053     int
2054     listening (player *pl, int new_value = -1)
2055     CODE:
2056     RETVAL = pl->listening;
2057     if (new_value >= 0)
2058     pl->listening = new_value;
2059     OUTPUT:
2060     RETVAL
2061    
2062 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2063 root 1.45 PROTOTYPE: $;$$$
2064 root 1.1 PPCODE:
2065 root 1.45 if (GIMME_V != G_VOID)
2066     {
2067     EXTEND (SP, 3);
2068     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2069     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2070     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2071     }
2072 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2073     if (x) sv_to (x, pl->bed_x);
2074     if (y) sv_to (y, pl->bed_y);
2075 root 1.1
2076     void
2077     list ()
2078     PPCODE:
2079 root 1.128 for_all_players (pl)
2080 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2081 root 1.1
2082    
2083     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2084    
2085 root 1.61 int invoke (maptile *map, int event, ...)
2086 root 1.18 CODE:
2087     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2088 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2089     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2090 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2091 root 1.25 OUTPUT: RETVAL
2092 root 1.18
2093 root 1.61 SV *registry (maptile *map)
2094 root 1.12
2095 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2096 root 1.1
2097 root 1.116 void
2098     maptile::instantiate ()
2099    
2100     maptile *new ()
2101 root 1.1 PROTOTYPE:
2102     CODE:
2103 root 1.116 RETVAL = new maptile;
2104 root 1.1 OUTPUT:
2105     RETVAL
2106    
2107 root 1.116 void
2108 root 1.117 maptile::players ()
2109     PPCODE:
2110     if (GIMME_V == G_SCALAR)
2111 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2112 root 1.117 else if (GIMME_V == G_ARRAY)
2113     {
2114     EXTEND (SP, THIS->players);
2115     for_all_players (pl)
2116     if (pl->ob && pl->ob->map == THIS)
2117 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2118 root 1.117 }
2119    
2120 root 1.156 void
2121 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2122 root 1.156 CODE:
2123     {
2124 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2125     croak ("maptile::add_underlay: palette must be arrayref");
2126 root 1.156
2127 root 1.168 palette = SvRV (palette);
2128 root 1.156
2129 root 1.168 STRLEN idxlen;
2130     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2131 root 1.156
2132 root 1.168 for (int x = 0; x < THIS->width; ++x)
2133     for (int y = 0; y < THIS->height; ++y)
2134     {
2135     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2136     if (op->flag [FLAG_IS_FLOOR])
2137     goto skip_space;
2138    
2139     {
2140     int offs = offset + y * stride + x;
2141     if (IN_RANGE_EXC (offs, 0, idxlen))
2142     {
2143     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2144     {
2145     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2146     ob->flag [FLAG_NO_MAP_SAVE] = true;
2147     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2148 root 1.200
2149     if (ob->randomitems)
2150     {
2151 root 1.203 if (!ob->above)
2152     {
2153     ob->create_treasure (ob->randomitems);
2154    
2155     for (object *op = ob->above; op; op = op->above)
2156     op->flag [FLAG_NO_MAP_SAVE] = true;
2157     }
2158    
2159 root 1.200 ob->randomitems = 0;
2160     }
2161 root 1.168 }
2162     }
2163     }
2164 root 1.156
2165 root 1.168 skip_space: ;
2166     }
2167     }
2168    
2169     void
2170     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2171     CODE:
2172     {
2173     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2174     croak ("maptile::set_regiondata: palette must be arrayref");
2175    
2176     palette = SvRV (palette);
2177    
2178     STRLEN idxlen;
2179     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2180    
2181     region **regionmap = (region **)malloc (
2182     (av_len ((AV *)palette) + 1) * sizeof (region *));
2183     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2184    
2185     for (int i = av_len ((AV *)palette) + 1; i--; )
2186     regionmap [i] = region::find (
2187     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2188    
2189     for (int y = 0; y < THIS->height; ++y)
2190     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2191    
2192     sfree (THIS->regions, THIS->size ());
2193     free (THIS->regionmap);
2194    
2195     THIS->regions = regions;
2196 root 1.156 THIS->regionmap = regionmap;
2197     }
2198    
2199 root 1.193 void
2200     maptile::create_region_treasure ()
2201     CODE:
2202     {
2203     object *op = object::create ();
2204     op->type = FLOOR;
2205     op->map = THIS;
2206    
2207     for (int x = 0; x < THIS->width; ++x)
2208     for (int y = 0; y < THIS->height; ++y)
2209     {
2210     region *rgn = THIS->region (x, y);
2211    
2212     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2213     if (rgn->treasure && rndm () < rgn->treasure_density)
2214     {
2215     op->x = x;
2216     op->y = y;
2217     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2218     }
2219     }
2220    
2221     op->destroy ();
2222     }
2223    
2224 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2225 root 1.1
2226 root 1.74 int out_of_map (maptile *map, int x, int y)
2227    
2228 root 1.29 void
2229 root 1.61 trigger (maptile *map, long connection, bool state = true)
2230 root 1.29 CODE:
2231     activate_connection (map, connection, state);
2232    
2233     void
2234 root 1.61 get_connection (maptile *map, long connection)
2235 root 1.29 PPCODE:
2236     oblinkpt *obp = get_connection_links (map, connection);
2237     if (obp)
2238     for (objectlink *ol = obp->link; ol; ol = ol->next)
2239 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2240 root 1.29
2241 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2242 root 1.1
2243 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2244 root 1.1
2245 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2246 root 1.1 C_ARGS: str, map, nx, ny
2247    
2248     void
2249 root 1.140 get_map_flags (maptile *map, int x, int y)
2250 root 1.1 PPCODE:
2251     {
2252 root 1.61 maptile *nmap = 0;
2253 root 1.1 I16 nx = 0, ny = 0;
2254 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2255 root 1.1
2256     EXTEND (SP, 4);
2257     PUSHs (sv_2mortal (newSViv (flags)));
2258    
2259     if (GIMME_V == G_ARRAY)
2260     {
2261     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2262     PUSHs (sv_2mortal (newSViv (nx)));
2263     PUSHs (sv_2mortal (newSViv (ny)));
2264     }
2265     }
2266    
2267     void
2268 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2269 root 1.1 PROTOTYPE: $$$
2270     PPCODE:
2271     {
2272     object *o;
2273 root 1.61 maptile *nmap = 0;
2274 root 1.1 I16 nx, ny;
2275    
2276 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2277 root 1.1
2278     if (nmap)
2279     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2280     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2281     }
2282    
2283     SV *
2284 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2285 root 1.1 PROTOTYPE: $$$
2286     ALIAS:
2287     top_at = 1
2288     flags_at = 2
2289     light_at = 3
2290     move_block_at = 4
2291     move_slow_at = 5
2292     move_on_at = 6
2293     move_off_at = 7
2294     INIT:
2295 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2296 root 1.1 CODE:
2297     switch (ix)
2298     {
2299     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2300     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2301     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2302     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2303     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2304     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2305     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2306     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2307     }
2308 root 1.122 OUTPUT: RETVAL
2309 root 1.1
2310 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2311    
2312     void fix_walls_around (maptile *map, int x, int y)
2313 root 1.1
2314 root 1.117 # worst xs function of my life
2315 root 1.140 bool
2316 root 1.117 _create_random_map (\
2317 root 1.140 maptile *self,\
2318 root 1.183 utf8_string wallstyle,\
2319     utf8_string wall_name,\
2320     utf8_string floorstyle,\
2321     utf8_string monsterstyle,\
2322     utf8_string treasurestyle,\
2323     utf8_string layoutstyle,\
2324     utf8_string doorstyle,\
2325     utf8_string decorstyle,\
2326     utf8_string origin_map,\
2327     utf8_string final_map,\
2328     utf8_string exitstyle,\
2329     utf8_string this_map,\
2330     utf8_string exit_on_final_map,\
2331 root 1.146 int xsize,\
2332     int ysize,\
2333 root 1.117 int expand2x,\
2334     int layoutoptions1,\
2335     int layoutoptions2,\
2336     int layoutoptions3,\
2337     int symmetry,\
2338     int difficulty,\
2339     int difficulty_given,\
2340     float difficulty_increase,\
2341     int dungeon_level,\
2342     int dungeon_depth,\
2343     int decoroptions,\
2344     int orientation,\
2345     int origin_y,\
2346     int origin_x,\
2347 root 1.146 U32 random_seed,\
2348 root 1.117 val64 total_map_hp,\
2349     int map_layout_style,\
2350     int treasureoptions,\
2351     int symmetry_used,\
2352 root 1.137 region *region,\
2353 root 1.183 utf8_string custom\
2354 root 1.117 )
2355     CODE:
2356     {
2357     random_map_params rmp;
2358    
2359     assign (rmp.wallstyle , wallstyle);
2360     assign (rmp.wall_name , wall_name);
2361     assign (rmp.floorstyle , floorstyle);
2362     assign (rmp.monsterstyle , monsterstyle);
2363     assign (rmp.treasurestyle , treasurestyle);
2364     assign (rmp.layoutstyle , layoutstyle);
2365     assign (rmp.doorstyle , doorstyle);
2366     assign (rmp.decorstyle , decorstyle);
2367     assign (rmp.exitstyle , exitstyle);
2368     assign (rmp.exit_on_final_map, exit_on_final_map);
2369    
2370 root 1.122 rmp.origin_map = origin_map;
2371     rmp.final_map = final_map;
2372     rmp.this_map = this_map;
2373 root 1.146 rmp.xsize = xsize;
2374     rmp.ysize = ysize;
2375 root 1.117 rmp.expand2x = expand2x;
2376     rmp.layoutoptions1 = layoutoptions1;
2377     rmp.layoutoptions2 = layoutoptions2;
2378     rmp.layoutoptions3 = layoutoptions3;
2379     rmp.symmetry = symmetry;
2380     rmp.difficulty = difficulty;
2381     rmp.difficulty_given = difficulty_given;
2382     rmp.difficulty_increase = difficulty_increase;
2383     rmp.dungeon_level = dungeon_level;
2384     rmp.dungeon_depth = dungeon_depth;
2385     rmp.decoroptions = decoroptions;
2386     rmp.orientation = orientation;
2387     rmp.origin_y = origin_y;
2388     rmp.origin_x = origin_x;
2389     rmp.random_seed = random_seed;
2390     rmp.total_map_hp = total_map_hp;
2391     rmp.map_layout_style = map_layout_style;
2392     rmp.treasureoptions = treasureoptions;
2393     rmp.symmetry_used = symmetry_used;
2394     rmp.region = region;
2395 root 1.137 rmp.custom = custom;
2396 root 1.117
2397 root 1.140 RETVAL = self->generate_random_map (&rmp);
2398 root 1.117 }
2399     OUTPUT:
2400     RETVAL
2401    
2402 root 1.19 MODULE = cf PACKAGE = cf::arch
2403 root 1.1
2404 root 1.183 archetype *find (utf8_string name)
2405 elmex 1.36 CODE:
2406 root 1.60 RETVAL = archetype::find (name);
2407 elmex 1.36 OUTPUT:
2408     RETVAL
2409    
2410 root 1.19 archetype *first()
2411 root 1.1 PROTOTYPE:
2412 root 1.19 CODE:
2413     RETVAL = first_archetype;
2414     OUTPUT: RETVAL
2415 root 1.1
2416 root 1.212 object *instantiate (archetype *arch)
2417     CODE:
2418     RETVAL = arch_to_object (arch);
2419     OUTPUT:
2420     RETVAL
2421    
2422 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2423 root 1.1
2424 root 1.19 MODULE = cf PACKAGE = cf::party
2425 root 1.1
2426 root 1.19 partylist *first ()
2427 root 1.1 PROTOTYPE:
2428 root 1.19 CODE:
2429     RETVAL = get_firstparty ();
2430     OUTPUT: RETVAL
2431 root 1.1
2432 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2433 root 1.1
2434 root 1.19 MODULE = cf PACKAGE = cf::region
2435 root 1.1
2436 root 1.161 void
2437     list ()
2438     PPCODE:
2439     for_all_regions (rgn)
2440     XPUSHs (sv_2mortal (to_sv (rgn)));
2441    
2442 root 1.183 region *find (utf8_string name)
2443 root 1.161 PROTOTYPE: $
2444 root 1.19 CODE:
2445 root 1.161 RETVAL = region::find (name);
2446 root 1.19 OUTPUT: RETVAL
2447 root 1.1
2448 root 1.183 region *find_fuzzy (utf8_string name)
2449 root 1.122 PROTOTYPE: $
2450     CODE:
2451 root 1.161 RETVAL = region::find_fuzzy (name);
2452 root 1.122 OUTPUT: RETVAL
2453    
2454 root 1.186 int specificity (region *rgn)
2455     CODE:
2456     RETVAL = 0;
2457     while (rgn = rgn->parent)
2458     RETVAL++;
2459     OUTPUT: RETVAL
2460    
2461 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2462 root 1.1
2463 root 1.19 MODULE = cf PACKAGE = cf::living
2464 root 1.1
2465 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2466 root 1.1
2467 root 1.76 MODULE = cf PACKAGE = cf::settings
2468    
2469 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2470 root 1.76
2471 root 1.84 MODULE = cf PACKAGE = cf::client
2472 root 1.79
2473 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2474 root 1.79
2475 root 1.84 int invoke (client *ns, int event, ...)
2476 root 1.79 CODE:
2477 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2478 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2479     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2480 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2481 root 1.79 OUTPUT: RETVAL
2482    
2483 root 1.84 SV *registry (client *ns)
2484 root 1.79
2485 root 1.100 void
2486     list ()
2487     PPCODE:
2488     EXTEND (SP, clients.size ());
2489     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2490     PUSHs (sv_2mortal (to_sv (*i)));
2491    
2492 root 1.88 void
2493 root 1.100 client::send_packet (SV *packet)
2494     CODE:
2495     {
2496     STRLEN len;
2497     char *buf = SvPVbyte (packet, len);
2498    
2499     THIS->send_packet (buf, len);
2500     }
2501    
2502 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2503    
2504 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2505 root 1.176
2506 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2507 root 1.176
2508 root 1.183 faceidx alloc (utf8_string name)
2509 root 1.176 CODE:
2510     {
2511     do
2512     {
2513     RETVAL = faces.size ();
2514 root 1.177 faces.resize (RETVAL + 1);
2515 root 1.176 }
2516     while (!RETVAL); // crude way to leave index 0
2517    
2518     faces [RETVAL].name = name;
2519     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2520    
2521     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2522     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2523     }
2524     OUTPUT: RETVAL
2525    
2526 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2527 root 1.176 CODE:
2528 root 1.177 faceinfo *f = face_info (idx);
2529     assert (f);
2530     f->visibility = visibility;
2531     f->magicmap = magicmap;
2532 root 1.176
2533 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2534 root 1.177 CODE:
2535 root 1.184 faceinfo *f = face_info (idx); assert (f);
2536     f->smooth = smooth;
2537     f->smoothlevel = smoothlevel;
2538 root 1.177
2539     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2540 root 1.176 CODE:
2541 root 1.182 {
2542 root 1.176 facedata *d = face_data (idx, faceset);
2543 root 1.177 assert (d);
2544 root 1.181 sv_to (data, d->data);
2545     STRLEN clen;
2546     char *cdata = SvPVbyte (chksum, clen);
2547 root 1.182 clen = min (CHKSUM_SIZE, clen);
2548    
2549     if (memcmp (d->chksum, cdata, clen))
2550     {
2551     memcpy (d->chksum, cdata, clen);
2552    
2553     // invalidate existing client face info
2554     for_all_clients (ns)
2555     if (ns->faceset == faceset)
2556     {
2557     ns->faces_sent [idx] = false;
2558     ns->force_newmap = true;
2559     }
2560     }
2561     }
2562 root 1.176
2563 root 1.177 void invalidate (faceidx idx)
2564     CODE:
2565     for_all_clients (ns)
2566 root 1.182 {
2567     ns->faces_sent [idx] = false;
2568     ns->force_newmap = true;
2569     }
2570 root 1.177
2571     void invalidate_all ()
2572     CODE:
2573     for_all_clients (ns)
2574 root 1.182 {
2575     ns->faces_sent.reset ();
2576     ns->force_newmap = true;
2577     }
2578 root 1.177
2579 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2580    
2581     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2582    
2583     animidx anim_find (utf8_string name)
2584     CODE:
2585     RETVAL = animation::find (name).number;
2586     OUTPUT: RETVAL
2587    
2588     animidx set (utf8_string name, SV *frames, int facings = 1)
2589     CODE:
2590     {
2591     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2592     croak ("frames must be an arrayref");
2593    
2594     AV *av = (AV *)SvRV (frames);
2595    
2596     animation *anim = &animation::find (name);
2597     if (anim->number)
2598     {
2599     anim->resize (av_len (av) + 1);
2600     anim->facings = facings;
2601     }
2602     else
2603     anim = &animation::create (name, av_len (av) + 1, facings);
2604    
2605     for (int i = 0; i < anim->num_animations; ++i)
2606     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2607     }
2608     OUTPUT: RETVAL
2609    
2610     void invalidate_all ()
2611     CODE:
2612     for_all_clients (ns)
2613     ns->anims_sent.reset ();
2614