ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.206
Committed: Mon May 7 06:01:48 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.205: +6 -1 lines
Log Message:
do not output archetypes with names starting with type_ or class_, a bit of a hack

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