ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.248
Committed: Thu Sep 6 06:53:08 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.247: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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