ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.195
Committed: Tue Apr 24 00:42:02 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.194: +4 -2 lines
Log Message:
- implement a rudimentary framework for a "msg" command that
  replaces drawinfo and drawextinfo and allows for simpler usage
  in simple cases and extensibility for the less complex uses.
- moved the character race choosing logic into perl, making use
  of the new msg command if the client supports it.

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