ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.192
Committed: Tue Apr 17 20:41:15 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.191: +42 -0 lines
Log Message:
considerably speed up world gridmap loading through some xs magic

File Contents

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