ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.196
Committed: Fri Apr 27 02:23:07 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.195: +0 -9 lines
Log Message:
declare object lifecycle coded working

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