ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.197
Committed: Fri Apr 27 03:38:33 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.196: +10 -6 lines
Log Message:
- allow invoke in do_destroy (as used by disconnect e.g.)
- change mortal check to use real refcnt.

TODO: the semantics of sever vs. optimise on explicit vs. implicit destroy
needs to be determinded exactly and cleanly.

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