ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.208
Committed: Sat May 12 13:27:38 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.207: +3 -3 lines
Log Message:
*** empty log message ***

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