ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.194
Committed: Mon Apr 23 18:09:57 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.193: +4 -3 lines
Log Message:
- add format utility function.
- split dynbuf into dynbuf and dynbuf_text.
- use dynbuf_text for examine strings instead of
  outputting each line seperately. tried to use stringstreams
  but they add insane overheads (as does std::string, but less so).

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