ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.251
Committed: Sun Sep 9 12:52:48 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.250: +2 -0 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 root 1.249 object *retval = 0;
1150 root 1.247
1151 root 1.249 if (ref)
1152     {
1153     CALL_BEGIN (1);
1154     CALL_ARG (ref);
1155     CALL_CALL ("cf::object::deref", G_SCALAR);
1156    
1157     if (count)
1158     sv_to (POPs, retval);
1159 root 1.247
1160 root 1.249 CALL_END;
1161     }
1162 root 1.247
1163     return retval;
1164     }
1165    
1166 root 1.198 void
1167     log_backtrace (const char *msg)
1168     {
1169     #if HAVE_BACKTRACE
1170     void *addr [20];
1171     int size = backtrace (addr, 20);
1172    
1173     CALL_BEGIN (size);
1174     CALL_ARG (msg);
1175     for (int i = 0; i < size; ++i)
1176     CALL_ARG ((IV)addr [i]);
1177     CALL_CALL ("cf::_log_backtrace", G_VOID);
1178     CALL_END;
1179     #endif
1180     }
1181    
1182 root 1.116 /////////////////////////////////////////////////////////////////////////////
1183    
1184 root 1.80 struct EventAPI *watcher_base::GEventAPI;
1185 root 1.116 struct CoroAPI *coroapi::GCoroAPI;
1186 root 1.80
1187 root 1.124 int coroapi::cede_counter;
1188 root 1.220 tstamp coroapi::next_cede;
1189 root 1.189
1190     void coroapi::do_cede_to_tick ()
1191     {
1192     cede_counter = 0;
1193    
1194     cede ();
1195    
1196     next_cede += (TICK / CEDES_PER_TICK) * 0.99;
1197     if (next_cede > SvNV (sv_next_tick) - 0.02)
1198     next_cede = SvNV (sv_next_tick);
1199     }
1200    
1201     void coroapi::do_cede_every ()
1202     {
1203     cede_counter = 0;
1204    
1205     if (coroapi::nready ())
1206     coroapi::cede ();
1207     }
1208    
1209     void coroapi::do_cede_to_tick_every ()
1210     {
1211     cede_counter = 0;
1212    
1213     cede_to_tick ();
1214     }
1215 root 1.124
1216 root 1.188 void
1217     coroapi::wait_for_tick ()
1218     {
1219     CALL_BEGIN (0);
1220     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1221     CALL_END;
1222     }
1223    
1224     void
1225     coroapi::wait_for_tick_begin ()
1226     {
1227     CALL_BEGIN (0);
1228     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1229     CALL_END;
1230     }
1231    
1232     static void
1233     iw_dispatch (pe_event *ev)
1234 root 1.85 {
1235     iw *w = (iw *)ev->ext_data;
1236     w->call (*w);
1237     }
1238    
1239     void
1240     iw::alloc ()
1241     {
1242     pe = GEventAPI->new_idle (0, 0);
1243    
1244 root 1.150 WaREENTRANT_off (pe);
1245 root 1.85 pe->base.callback = (void *)iw_dispatch;
1246     pe->base.ext_data = (void *)this;
1247     }
1248    
1249 root 1.80 static void iow_dispatch (pe_event *ev)
1250     {
1251     iow *w = (iow *)ev->ext_data;
1252     w->call (*w, ((pe_ioevent *)ev)->got);
1253     }
1254    
1255     void
1256     iow::alloc ()
1257     {
1258     pe = GEventAPI->new_io (0, 0);
1259    
1260 root 1.150 WaREENTRANT_off (pe);
1261 root 1.80 pe->base.callback = (void *)iow_dispatch;
1262     pe->base.ext_data = (void *)this;
1263    
1264 root 1.81 pe->fd = -1;
1265     pe->poll = 0;
1266 root 1.80 }
1267    
1268 root 1.85 void
1269 root 1.80 iow::fd (int fd)
1270     {
1271     pe->fd = fd;
1272     }
1273    
1274     int
1275     iow::poll ()
1276     {
1277     return pe->poll;
1278     }
1279    
1280 root 1.85 void
1281 root 1.80 iow::poll (int events)
1282     {
1283 root 1.81 if (pe->poll != events)
1284     {
1285     if (pe->poll) stop ();
1286     pe->poll = events;
1287     if (pe->poll) start ();
1288     }
1289 root 1.80 }
1290    
1291 root 1.109 void
1292     _connect_to_perl ()
1293     {
1294     stash_cf = gv_stashpv ("cf" , 1);
1295    
1296     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1297     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1298     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1299     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1300     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1301     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1302     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1303     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1304     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1305    
1306 root 1.189 sv_runtime = get_sv ("cf::RUNTIME" , 1); sv_upgrade (sv_runtime , SVt_NV);
1307     sv_next_tick = get_sv ("cf::NEXT_TICK", 1); sv_upgrade (sv_next_tick, SVt_NV);
1308 root 1.116
1309 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1310     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1311     cb_object = get_av ("cf::CB_OBJECT", 1);
1312     cb_player = get_av ("cf::CB_PLAYER", 1);
1313     cb_client = get_av ("cf::CB_CLIENT", 1);
1314     cb_type = get_av ("cf::CB_TYPE" , 1);
1315     cb_map = get_av ("cf::CB_MAP" , 1);
1316     }
1317    
1318 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1319    
1320     BOOT:
1321     {
1322 root 1.116 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1323     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1324 root 1.80
1325 root 1.189 _connect_to_perl ();
1326    
1327 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1328 root 1.63
1329 root 1.220 //{
1330     // require_pv ("Time::HiRes");
1331     //
1332     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1333     // if (!svp) croak ("Time::HiRes is required");
1334     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1335     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1336     //}
1337 root 1.189
1338 root 1.1 static const struct {
1339     const char *name;
1340     IV iv;
1341     } *civ, const_iv[] = {
1342     # define const_iv(name) { # name, (IV)name },
1343 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1344 root 1.198 const_iv (logBacktrace)
1345 root 1.180
1346 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1347    
1348     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1349 root 1.180
1350 root 1.5 const_iv (MAX_TIME)
1351 root 1.189
1352 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1353     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1354     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1355     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1356     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1357     const_iv (body_wrist) const_iv (body_waist)
1358 root 1.205
1359 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1360     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1361     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1362     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1363     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1364     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1365     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1366     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1367     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1368     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1369     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1370     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1371     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1372     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1373     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1374     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1375     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1376     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1377     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1378     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1379     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1380     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1381     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1382     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1383     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1384     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1385     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1386     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1387 root 1.1
1388 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1389 root 1.14
1390 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1391     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1392 root 1.1
1393 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1394     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1395     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1396     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1397     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1398     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1399     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1400    
1401     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1402     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1403 root 1.1 const_iv (WEAP_BLUD)
1404    
1405 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1406 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1407 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1408     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1409     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1410     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1411     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1412     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1413     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1414     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1415     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1416     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1417     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1418     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1419     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1420     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1421     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1422     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1423     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1424     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1425     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1426     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1427     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1428 root 1.245 const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1429 root 1.189 const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1430     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1431    
1432     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1433     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1434     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1435     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1436 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1437 root 1.250 const_iv (NDI_NOCREATE) const_iv (NDI_CLEAR)
1438 root 1.1
1439 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1440     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1441    
1442     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1443    
1444 root 1.212 const_iv (SP_RAISE_DEAD)
1445     const_iv (SP_RUNE)
1446     const_iv (SP_MAKE_MARK)
1447     const_iv (SP_BOLT)
1448     const_iv (SP_BULLET)
1449     const_iv (SP_EXPLOSION)
1450     const_iv (SP_CONE)
1451     const_iv (SP_BOMB)
1452     const_iv (SP_WONDER)
1453     const_iv (SP_SMITE)
1454     const_iv (SP_MAGIC_MISSILE)
1455     const_iv (SP_SUMMON_GOLEM)
1456     const_iv (SP_DIMENSION_DOOR)
1457     const_iv (SP_MAGIC_MAPPING)
1458     const_iv (SP_MAGIC_WALL)
1459     const_iv (SP_DESTRUCTION)
1460     const_iv (SP_PERCEIVE_SELF)
1461     const_iv (SP_WORD_OF_RECALL)
1462     const_iv (SP_INVISIBLE)
1463     const_iv (SP_PROBE)
1464     const_iv (SP_HEALING)
1465     const_iv (SP_CREATE_FOOD)
1466     const_iv (SP_EARTH_TO_DUST)
1467     const_iv (SP_CHANGE_ABILITY)
1468     const_iv (SP_BLESS)
1469     const_iv (SP_CURSE)
1470     const_iv (SP_SUMMON_MONSTER)
1471     const_iv (SP_CHARGING)
1472     const_iv (SP_POLYMORPH)
1473     const_iv (SP_ALCHEMY)
1474     const_iv (SP_REMOVE_CURSE)
1475     const_iv (SP_IDENTIFY)
1476     const_iv (SP_DETECTION)
1477     const_iv (SP_MOOD_CHANGE)
1478     const_iv (SP_MOVING_BALL)
1479     const_iv (SP_SWARM)
1480     const_iv (SP_CHANGE_MANA)
1481     const_iv (SP_DISPEL_RUNE)
1482     const_iv (SP_CREATE_MISSILE)
1483     const_iv (SP_CONSECRATE)
1484     const_iv (SP_ANIMATE_WEAPON)
1485     const_iv (SP_LIGHT)
1486     const_iv (SP_CHANGE_MAP_LIGHT)
1487     const_iv (SP_FAERY_FIRE)
1488     const_iv (SP_CAUSE_DISEASE)
1489     const_iv (SP_AURA)
1490     const_iv (SP_TOWN_PORTAL)
1491     const_iv (SP_PARTY_SPELL)
1492    
1493 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1494     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1495 root 1.1 const_iv (F_LOCKED)
1496    
1497 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1498    
1499     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1500     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1501    
1502     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1503    
1504     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1505     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1506    
1507     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1508     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1509    
1510     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1511    
1512     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1513     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1514     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1515     const_iv (M_ICE) const_iv (M_SPECIAL)
1516    
1517     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1518     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1519    
1520     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1521     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1522     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1523     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1524     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1525     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1526     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1527     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1528     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1529     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1530 root 1.1 const_iv (SK_POISON_NAIL)
1531    
1532 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1533     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1534     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1535     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1536     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1537     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1538    
1539     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1540    
1541     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1542     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1543     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1544     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1545     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1546     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1547     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1548    
1549     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1550    
1551     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1552     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1553    
1554 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1555    
1556 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1557    
1558     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1559 root 1.99
1560 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1561 root 1.117
1562     // random map generator
1563 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1564     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1565    
1566     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1567     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1568     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1569    
1570     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1571     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1572 root 1.195
1573     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1574     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1575     const_iv (GT_MINIMAL)
1576 root 1.238
1577     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1578     const_iv (FT_RSRC) const_iv (FT_NUM)
1579 root 1.1 };
1580    
1581     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1582 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1583 root 1.1
1584     static const struct {
1585     const char *name;
1586 root 1.14 int skip;
1587 root 1.7 IV klass;
1588 root 1.1 IV iv;
1589 root 1.6 } *eiv, event_iv[] = {
1590 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1591 root 1.6 # include "eventinc.h"
1592     # undef def
1593     };
1594    
1595     AV *av = get_av ("cf::EVENT", 1);
1596    
1597     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1598 root 1.7 {
1599     AV *event = newAV ();
1600 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1601 root 1.7 av_push (event, newSViv (eiv->klass));
1602     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1603 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1604 root 1.7 }
1605 root 1.14 }
1606    
1607 root 1.109 void _connect_to_perl ()
1608 root 1.14
1609 root 1.210 void _recalc_want ()
1610    
1611 root 1.47 void _global_reattach ()
1612 root 1.14 CODE:
1613     {
1614     // reattach to all attachable objects in the game.
1615 root 1.128 for_all_clients (ns)
1616     ns->reattach ();
1617 root 1.96
1618 root 1.128 for_all_objects (op)
1619 root 1.109 op->reattach ();
1620 root 1.1 }
1621    
1622 root 1.192 # support function for map-world.ext
1623     void _quantise (SV *data_sv, SV *plt_sv)
1624     CODE:
1625     {
1626     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1627     croak ("_quantise called with invalid agruments");
1628    
1629     plt_sv = SvRV (plt_sv);
1630     SV **plt = AvARRAY (plt_sv);
1631     int plt_count = AvFILL (plt_sv) + 1;
1632    
1633     STRLEN len;
1634     char *data = SvPVbyte (data_sv, len);
1635     char *dst = data;
1636    
1637     while (len >= 3)
1638     {
1639     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1640     {
1641     char *val = SvPVX (*val_sv);
1642    
1643     if (val [0] == data [0]
1644     && val [1] == data [1]
1645     && val [2] == data [2])
1646     {
1647     *dst++ = val [3];
1648     goto next;
1649     }
1650     }
1651    
1652     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1653     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1654     dst - SvPVX (data_sv), len);
1655    
1656     next:
1657     data += 3;
1658     len -= 3;
1659     }
1660    
1661     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1662     }
1663    
1664 root 1.236 void _post_tick ()
1665     CODE:
1666     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1667    
1668     NV till_cede ()
1669     CODE:
1670     RETVAL = coroapi::next_cede - now ();
1671     OUTPUT:
1672     RETVAL
1673    
1674     NV till_tick ()
1675     CODE:
1676     RETVAL = SvNV (sv_next_tick) - now ();
1677     OUTPUT:
1678     RETVAL
1679    
1680 root 1.1 NV floor (NV x)
1681    
1682     NV ceil (NV x)
1683    
1684 root 1.143 NV rndm (...)
1685     CODE:
1686     switch (items)
1687     {
1688     case 0: RETVAL = rndm (); break;
1689     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1690     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1691     default: croak ("cf::rndm requires none, one or two parameters."); break;
1692     }
1693     OUTPUT:
1694     RETVAL
1695    
1696 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1697     CODE:
1698     RETVAL = clamp (value, min_value, max_value);
1699     OUTPUT:
1700     RETVAL
1701    
1702     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1703     CODE:
1704     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1705     OUTPUT:
1706     RETVAL
1707    
1708     void cede_to_tick ()
1709     CODE:
1710     coroapi::cede_to_tick ();
1711    
1712 root 1.5 void server_tick ()
1713 root 1.116 CODE:
1714 root 1.220 NOW = now ();
1715 root 1.116 runtime = SvNVx (sv_runtime);
1716     server_tick ();
1717 root 1.5
1718 root 1.1 void
1719 root 1.198 log_backtrace (utf8_string msg)
1720    
1721     void
1722     LOG (int flags, utf8_string msg)
1723 root 1.1 PROTOTYPE: $$
1724 root 1.198 C_ARGS: flags, "%s", msg
1725 root 1.1
1726 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1727 root 1.1 PROTOTYPE: $$
1728    
1729 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1730 root 1.1 PROTOTYPE: $$
1731    
1732     void
1733     sub_generation_inc ()
1734     CODE:
1735     PL_sub_generation++;
1736    
1737 root 1.183 const_octet_string
1738 root 1.1 mapdir ()
1739     PROTOTYPE:
1740     ALIAS:
1741     mapdir = 0
1742     uniquedir = 1
1743     tmpdir = 2
1744     confdir = 3
1745     localdir = 4
1746     playerdir = 5
1747     datadir = 6
1748     CODE:
1749 root 1.19 switch (ix)
1750     {
1751     case 0: RETVAL = settings.mapdir ; break;
1752     case 1: RETVAL = settings.uniquedir; break;
1753     case 2: RETVAL = settings.tmpdir ; break;
1754     case 3: RETVAL = settings.confdir ; break;
1755     case 4: RETVAL = settings.localdir ; break;
1756     case 5: RETVAL = settings.playerdir; break;
1757     case 6: RETVAL = settings.datadir ; break;
1758     }
1759 root 1.1 OUTPUT: RETVAL
1760    
1761 root 1.120 void abort ()
1762    
1763 root 1.199 void reset_signals ()
1764    
1765 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1766 root 1.144
1767 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1768 root 1.134
1769 root 1.116 void emergency_save ()
1770    
1771 root 1.156 void _exit (int status = EXIT_SUCCESS)
1772    
1773 root 1.149 UV sv_2watcher (SV *w)
1774     CODE:
1775     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1776     OUTPUT:
1777     RETVAL
1778    
1779 root 1.125 #if _POSIX_MEMLOCK
1780    
1781     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1782    
1783     int munlockall ()
1784    
1785     #endif
1786    
1787 root 1.183 int find_animation (utf8_string text)
1788 root 1.1 PROTOTYPE: $
1789    
1790 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1791 root 1.1
1792 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1793 root 1.1
1794     int
1795     exp_to_level (val64 exp)
1796     CODE:
1797     {
1798     int i = 0;
1799    
1800     RETVAL = settings.max_level;
1801    
1802     for (i = 1; i <= settings.max_level; i++)
1803     {
1804     if (levels[i] > exp)
1805     {
1806     RETVAL = i - 1;
1807     break;
1808     }
1809     }
1810     }
1811     OUTPUT: RETVAL
1812    
1813     val64
1814     level_to_min_exp (int level)
1815     CODE:
1816     if (level > settings.max_level)
1817     RETVAL = levels[settings.max_level];
1818     else if (level < 1)
1819     RETVAL = 0;
1820     else
1821     RETVAL = levels[level];
1822     OUTPUT: RETVAL
1823    
1824     SV *
1825     resistance_to_string (int atnr)
1826     CODE:
1827     if (atnr >= 0 && atnr < NROFATTACKS)
1828     RETVAL = newSVpv (resist_plus[atnr], 0);
1829     else
1830     XSRETURN_UNDEF;
1831     OUTPUT: RETVAL
1832    
1833 root 1.162 bool
1834 root 1.183 load_resource_file (octet_string filename)
1835 root 1.162
1836 root 1.97 MODULE = cf PACKAGE = cf::attachable
1837    
1838 root 1.27 int
1839 root 1.97 valid (SV *obj)
1840 root 1.27 CODE:
1841     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1842     OUTPUT:
1843     RETVAL
1844    
1845 root 1.164 void
1846     debug_trace (attachable *obj, bool on = true)
1847     CODE:
1848     obj->flags &= ~attachable::F_DEBUG_TRACE;
1849     if (on)
1850     obj->flags |= attachable::F_DEBUG_TRACE;
1851    
1852 root 1.153 int mortals_size ()
1853     CODE:
1854     RETVAL = attachable::mortals.size ();
1855     OUTPUT: RETVAL
1856    
1857     #object *mortals (U32 index)
1858     # CODE:
1859     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1860     # OUTPUT: RETVAL
1861    
1862 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1863 root 1.115
1864 root 1.101 MODULE = cf PACKAGE = cf::global
1865    
1866     int invoke (SV *klass, int event, ...)
1867     CODE:
1868     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1869     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1870     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1871 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1872 root 1.101 OUTPUT: RETVAL
1873    
1874 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1875    
1876 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1877 root 1.62
1878 root 1.18 int invoke (object *op, int event, ...)
1879     CODE:
1880     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1881 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1882     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1883 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1884 root 1.18 OUTPUT: RETVAL
1885    
1886     SV *registry (object *op)
1887    
1888 root 1.134 int objects_size ()
1889     CODE:
1890     RETVAL = objects.size ();
1891     OUTPUT: RETVAL
1892    
1893     object *objects (U32 index)
1894     CODE:
1895     RETVAL = index < objects.size () ? objects [index] : 0;
1896     OUTPUT: RETVAL
1897    
1898     int actives_size ()
1899     CODE:
1900     RETVAL = actives.size ();
1901     OUTPUT: RETVAL
1902    
1903     object *actives (U32 index)
1904 root 1.57 CODE:
1905 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1906 root 1.57 OUTPUT: RETVAL
1907    
1908 root 1.215 const char *slot_use_name (U32 slot)
1909 root 1.205 ALIAS:
1910 root 1.215 slot_nonuse_name = 1
1911 root 1.205 CODE:
1912     {
1913     if (slot >= NUM_BODY_LOCATIONS)
1914     croak ("body slot index out of range");
1915    
1916     switch (ix)
1917     {
1918 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1919     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1920 root 1.205 }
1921     }
1922     OUTPUT:
1923     RETVAL
1924    
1925 root 1.1 # missing properties
1926    
1927 root 1.54 object *head (object *op)
1928     PROTOTYPE: $
1929     CODE:
1930 root 1.134 RETVAL = op->head_ ();
1931 root 1.54 OUTPUT: RETVAL
1932    
1933 root 1.1 void
1934     inv (object *obj)
1935     PROTOTYPE: $
1936     PPCODE:
1937     {
1938     object *o;
1939     for (o = obj->inv; o; o = o->below)
1940 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1941 root 1.1 }
1942    
1943 root 1.102 void
1944     set_animation (object *op, int idx)
1945     CODE:
1946     SET_ANIMATION (op, idx);
1947    
1948 elmex 1.160 int
1949     num_animations (object *op)
1950     CODE:
1951     RETVAL = NUM_ANIMATIONS (op);
1952     OUTPUT: RETVAL
1953    
1954 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1955     ALIAS:
1956     slot_used = 1
1957     CODE:
1958     {
1959     if (slot >= NUM_BODY_LOCATIONS)
1960     croak ("body slot index out of range");
1961    
1962 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1963 root 1.205
1964     if (items > 2)
1965     if (ix)
1966 root 1.208 op->slot[slot].used = value;
1967     else
1968 root 1.205 op->slot[slot].info = value;
1969     }
1970     OUTPUT:
1971     RETVAL
1972    
1973 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1974 root 1.58
1975     object *find_marked_object (object *op)
1976    
1977 root 1.109 int need_identify (object *obj);
1978 root 1.1
1979     int apply_shop_mat (object *shop_mat, object *op);
1980    
1981 pippijn 1.172 int move_player (object *op, int dir)
1982     CODE:
1983     RETVAL = move_player (op, dir);
1984     OUTPUT:
1985     RETVAL
1986    
1987 root 1.27 int move (object *op, int dir, object *originator = op)
1988     CODE:
1989     RETVAL = move_ob (op, dir, originator);
1990     OUTPUT:
1991     RETVAL
1992 root 1.1
1993 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1994     CODE:
1995     manual_apply (applied, applier, flags);
1996 root 1.1
1997 root 1.74 void apply_below (object *op)
1998     CODE:
1999     player_apply_below (op);
2000 root 1.1
2001 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
2002    
2003 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
2004 root 1.1
2005     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
2006    
2007 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
2008 root 1.1
2009 root 1.116 #//TODO
2010     object *clone_ (object *op, int recursive = 0)
2011 root 1.74 CODE:
2012     if (recursive)
2013     RETVAL = object_create_clone (op);
2014     else
2015     {
2016     RETVAL = object::create ();
2017 root 1.75 op->copy_to (RETVAL);
2018 root 1.74 }
2019     OUTPUT: RETVAL
2020 root 1.1
2021 root 1.74 int pay_item (object *op, object *buyer)
2022     CODE:
2023     RETVAL = pay_for_item (op, buyer);
2024     OUTPUT: RETVAL
2025 root 1.1
2026 root 1.74 int pay_amount (object *op, uint64 amount)
2027     CODE:
2028     RETVAL = pay_for_amount (amount, op);
2029     OUTPUT: RETVAL
2030 root 1.1
2031     void pay_player (object *op, uint64 amount)
2032    
2033 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
2034 root 1.1
2035 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
2036 root 1.1
2037 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
2038     CODE:
2039     do_learn_spell (op, sp, special_prayer);
2040 root 1.1
2041 root 1.74 void forget_spell (object *op, object *sp)
2042     CODE:
2043     do_forget_spell (op, query_name (sp));
2044 root 1.1
2045 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2046 root 1.74 CODE:
2047     RETVAL = check_spell_known (op, spellname);
2048     OUTPUT: RETVAL
2049 root 1.1
2050 root 1.74 int query_money (object *op)
2051 root 1.1 ALIAS: money = 0
2052    
2053 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2054 root 1.1 ALIAS: cost = 0
2055    
2056 root 1.74 void spring_trap (object *op, object *victim)
2057 root 1.1
2058 root 1.74 int check_trigger (object *op, object *cause)
2059 root 1.1
2060 root 1.74 void drop (object *who, object *op)
2061 root 1.1
2062 root 1.74 void pick_up (object *who, object *op)
2063 root 1.1
2064 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
2065 root 1.1
2066 root 1.102 void update_object (object *op, int action)
2067 root 1.1
2068 root 1.183 object *cf_create_object_by_name (utf8_string name)
2069 root 1.1
2070 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2071 root 1.1
2072     void player_lvl_adj (object *who, object *skill = 0)
2073    
2074     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2075    
2076     int calc_skill_exp (object *who, object *op, object *skill);
2077    
2078     void push_button (object *op);
2079    
2080     void use_trigger (object *op);
2081    
2082 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2083 root 1.1
2084     void remove_button_link (object *op);
2085    
2086 elmex 1.232 void handle_apply_yield (object *op);
2087    
2088 root 1.1
2089     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2090    
2091     object *cf_insert_ob_in_ob (object *ob, object *where)
2092    
2093     # no clean way to get an object from an archetype - stupid idiotic
2094     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2095    
2096 root 1.183 object *new (utf8_string archetype = 0)
2097 root 1.1 PROTOTYPE: ;$
2098     CODE:
2099 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2100 root 1.1 OUTPUT:
2101     RETVAL
2102    
2103 root 1.225 object *find_object (U32 tag)
2104    
2105 root 1.218 # TODO: nuke
2106 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2107 root 1.1 PROTOTYPE: $$$$$$
2108     CODE:
2109     {
2110     int unused_type;
2111     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
2112     }
2113    
2114 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
2115 root 1.1
2116 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
2117 root 1.1
2118     object *get_nearest_player (object *ob)
2119     ALIAS: nearest_player = 0
2120     PREINIT:
2121     extern object *get_nearest_player (object *);
2122    
2123     void rangevector (object *ob, object *other, int flags = 0)
2124     PROTOTYPE: $$;$
2125     PPCODE:
2126     {
2127     rv_vector rv;
2128     get_rangevector (ob, other, &rv, flags);
2129     EXTEND (SP, 5);
2130     PUSHs (newSVuv (rv.distance));
2131     PUSHs (newSViv (rv.distance_x));
2132     PUSHs (newSViv (rv.distance_y));
2133     PUSHs (newSViv (rv.direction));
2134     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
2135     }
2136    
2137     bool on_same_map_as (object *ob, object *other)
2138     CODE:
2139     RETVAL = on_same_map (ob, other);
2140     OUTPUT: RETVAL
2141    
2142 root 1.183 const_utf8_string
2143 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2144 root 1.1 CODE:
2145 root 1.58 RETVAL = query_base_name (op, plural);
2146 root 1.1 OUTPUT: RETVAL
2147    
2148 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
2149    
2150 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2151    
2152     player *player (object *op)
2153     CODE:
2154     RETVAL = op->contr;
2155     OUTPUT: RETVAL
2156    
2157 root 1.105 void check_score (object *op)
2158    
2159 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2160 root 1.120 CODE:
2161     new_draw_info (flags, 0, op, txt);
2162 root 1.1
2163     void kill_player (object *op)
2164    
2165 root 1.58 void esrv_update_item (object *op, int what, object *item)
2166     C_ARGS: what, op, item
2167    
2168 root 1.183 int command_summon (object *op, utf8_string params)
2169 root 1.67
2170 root 1.183 int command_arrest (object *op, utf8_string params)
2171 root 1.67
2172 root 1.66
2173 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2174 root 1.1
2175 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2176 root 1.62
2177 root 1.18 int invoke (player *pl, int event, ...)
2178     CODE:
2179     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2180 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2181     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2182 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2183 root 1.18 OUTPUT: RETVAL
2184    
2185 root 1.12 SV *registry (player *pl)
2186 root 1.1
2187 root 1.102 void
2188     save_stats (player *pl)
2189     CODE:
2190     pl->ob->stats.hp = pl->ob->stats.maxhp;
2191     pl->ob->stats.sp = pl->ob->stats.maxsp;
2192     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2193     pl->orig_stats = pl->ob->stats;
2194    
2195 root 1.217 void clear_los (player *pl)
2196    
2197 root 1.1 void cf_player_move (player *pl, int dir)
2198    
2199     bool
2200     cell_visible (player *pl, int dx, int dy)
2201     CODE:
2202 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2203     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2204 root 1.1 OUTPUT:
2205     RETVAL
2206    
2207 root 1.4 void
2208 root 1.1 send (player *pl, SV *packet)
2209     CODE:
2210     {
2211     STRLEN len;
2212     char *buf = SvPVbyte (packet, len);
2213    
2214 root 1.100 if (pl->ns)
2215     pl->ns->send_packet (buf, len);
2216 root 1.1 }
2217    
2218     int
2219     listening (player *pl, int new_value = -1)
2220     CODE:
2221     RETVAL = pl->listening;
2222     if (new_value >= 0)
2223     pl->listening = new_value;
2224     OUTPUT:
2225     RETVAL
2226    
2227 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2228 root 1.45 PROTOTYPE: $;$$$
2229 root 1.1 PPCODE:
2230 root 1.45 if (GIMME_V != G_VOID)
2231     {
2232     EXTEND (SP, 3);
2233     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2234     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2235     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2236     }
2237 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2238     if (x) sv_to (x, pl->bed_x);
2239     if (y) sv_to (y, pl->bed_y);
2240 root 1.1
2241     void
2242     list ()
2243     PPCODE:
2244 root 1.128 for_all_players (pl)
2245 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2246 root 1.1
2247    
2248     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2249    
2250 root 1.61 int invoke (maptile *map, int event, ...)
2251 root 1.18 CODE:
2252     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2253 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2254     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2255 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2256 root 1.25 OUTPUT: RETVAL
2257 root 1.18
2258 root 1.61 SV *registry (maptile *map)
2259 root 1.12
2260 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2261 root 1.1
2262 root 1.116 void
2263     maptile::instantiate ()
2264    
2265     maptile *new ()
2266 root 1.1 PROTOTYPE:
2267     CODE:
2268 root 1.116 RETVAL = new maptile;
2269 root 1.1 OUTPUT:
2270     RETVAL
2271    
2272 root 1.116 void
2273 root 1.117 maptile::players ()
2274     PPCODE:
2275     if (GIMME_V == G_SCALAR)
2276 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2277 root 1.117 else if (GIMME_V == G_ARRAY)
2278     {
2279     EXTEND (SP, THIS->players);
2280     for_all_players (pl)
2281     if (pl->ob && pl->ob->map == THIS)
2282 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2283 root 1.117 }
2284    
2285 root 1.156 void
2286 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2287 root 1.156 CODE:
2288     {
2289 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2290     croak ("maptile::add_underlay: palette must be arrayref");
2291 root 1.156
2292 root 1.168 palette = SvRV (palette);
2293 root 1.156
2294 root 1.168 STRLEN idxlen;
2295     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2296 root 1.156
2297 root 1.168 for (int x = 0; x < THIS->width; ++x)
2298     for (int y = 0; y < THIS->height; ++y)
2299     {
2300     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2301     if (op->flag [FLAG_IS_FLOOR])
2302     goto skip_space;
2303    
2304     {
2305     int offs = offset + y * stride + x;
2306     if (IN_RANGE_EXC (offs, 0, idxlen))
2307     {
2308     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2309     {
2310     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2311     ob->flag [FLAG_NO_MAP_SAVE] = true;
2312     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2313 root 1.200
2314     if (ob->randomitems)
2315     {
2316 root 1.203 if (!ob->above)
2317     {
2318     ob->create_treasure (ob->randomitems);
2319    
2320     for (object *op = ob->above; op; op = op->above)
2321     op->flag [FLAG_NO_MAP_SAVE] = true;
2322     }
2323    
2324 root 1.200 ob->randomitems = 0;
2325     }
2326 root 1.168 }
2327     }
2328     }
2329 root 1.156
2330 root 1.168 skip_space: ;
2331     }
2332     }
2333    
2334     void
2335     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2336     CODE:
2337     {
2338     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2339     croak ("maptile::set_regiondata: palette must be arrayref");
2340    
2341     palette = SvRV (palette);
2342    
2343     STRLEN idxlen;
2344     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2345    
2346 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2347 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2348    
2349     for (int i = av_len ((AV *)palette) + 1; i--; )
2350 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2351 root 1.168
2352     for (int y = 0; y < THIS->height; ++y)
2353     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2354    
2355     sfree (THIS->regions, THIS->size ());
2356 root 1.230 delete [] THIS->regionmap;
2357 root 1.168
2358     THIS->regions = regions;
2359 root 1.156 THIS->regionmap = regionmap;
2360     }
2361    
2362 root 1.193 void
2363     maptile::create_region_treasure ()
2364     CODE:
2365     {
2366     object *op = object::create ();
2367     op->type = FLOOR;
2368     op->map = THIS;
2369    
2370     for (int x = 0; x < THIS->width; ++x)
2371     for (int y = 0; y < THIS->height; ++y)
2372     {
2373     region *rgn = THIS->region (x, y);
2374    
2375     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2376     if (rgn->treasure && rndm () < rgn->treasure_density)
2377     {
2378     op->x = x;
2379     op->y = y;
2380     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2381     }
2382     }
2383    
2384     op->destroy ();
2385     }
2386    
2387 root 1.74 int out_of_map (maptile *map, int x, int y)
2388    
2389 root 1.29 void
2390 root 1.61 trigger (maptile *map, long connection, bool state = true)
2391 root 1.29 CODE:
2392     activate_connection (map, connection, state);
2393    
2394     void
2395 root 1.61 get_connection (maptile *map, long connection)
2396 root 1.29 PPCODE:
2397     oblinkpt *obp = get_connection_links (map, connection);
2398     if (obp)
2399     for (objectlink *ol = obp->link; ol; ol = ol->next)
2400 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2401 root 1.29
2402 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2403 root 1.1
2404 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2405 root 1.1
2406 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2407 root 1.1 C_ARGS: str, map, nx, ny
2408    
2409     void
2410 root 1.140 get_map_flags (maptile *map, int x, int y)
2411 root 1.1 PPCODE:
2412     {
2413 root 1.61 maptile *nmap = 0;
2414 root 1.1 I16 nx = 0, ny = 0;
2415 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2416 root 1.1
2417     EXTEND (SP, 4);
2418     PUSHs (sv_2mortal (newSViv (flags)));
2419    
2420     if (GIMME_V == G_ARRAY)
2421     {
2422     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2423     PUSHs (sv_2mortal (newSViv (nx)));
2424     PUSHs (sv_2mortal (newSViv (ny)));
2425     }
2426     }
2427    
2428     void
2429 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2430 root 1.1 PROTOTYPE: $$$
2431     PPCODE:
2432     {
2433     object *o;
2434 root 1.61 maptile *nmap = 0;
2435 root 1.1 I16 nx, ny;
2436    
2437 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2438 root 1.1
2439     if (nmap)
2440     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2441     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2442     }
2443    
2444     SV *
2445 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2446 root 1.1 PROTOTYPE: $$$
2447     ALIAS:
2448     top_at = 1
2449     flags_at = 2
2450     light_at = 3
2451     move_block_at = 4
2452     move_slow_at = 5
2453     move_on_at = 6
2454     move_off_at = 7
2455     INIT:
2456 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2457 root 1.1 CODE:
2458     switch (ix)
2459     {
2460     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2461     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2462     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2463     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2464     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2465     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2466     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2467     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2468     }
2469 root 1.122 OUTPUT: RETVAL
2470 root 1.1
2471 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2472    
2473     void fix_walls_around (maptile *map, int x, int y)
2474 root 1.1
2475 root 1.117 # worst xs function of my life
2476 root 1.140 bool
2477 root 1.117 _create_random_map (\
2478 root 1.140 maptile *self,\
2479 root 1.183 utf8_string wallstyle,\
2480     utf8_string wall_name,\
2481     utf8_string floorstyle,\
2482     utf8_string monsterstyle,\
2483     utf8_string treasurestyle,\
2484     utf8_string layoutstyle,\
2485     utf8_string doorstyle,\
2486     utf8_string decorstyle,\
2487     utf8_string origin_map,\
2488     utf8_string final_map,\
2489     utf8_string exitstyle,\
2490     utf8_string this_map,\
2491     utf8_string exit_on_final_map,\
2492 root 1.146 int xsize,\
2493     int ysize,\
2494 root 1.117 int expand2x,\
2495     int layoutoptions1,\
2496     int layoutoptions2,\
2497     int layoutoptions3,\
2498     int symmetry,\
2499     int difficulty,\
2500     int difficulty_given,\
2501     float difficulty_increase,\
2502     int dungeon_level,\
2503     int dungeon_depth,\
2504     int decoroptions,\
2505     int orientation,\
2506     int origin_y,\
2507     int origin_x,\
2508 root 1.146 U32 random_seed,\
2509 root 1.117 val64 total_map_hp,\
2510     int map_layout_style,\
2511     int treasureoptions,\
2512     int symmetry_used,\
2513 root 1.137 region *region,\
2514 root 1.183 utf8_string custom\
2515 root 1.117 )
2516     CODE:
2517     {
2518     random_map_params rmp;
2519    
2520     assign (rmp.wallstyle , wallstyle);
2521     assign (rmp.wall_name , wall_name);
2522     assign (rmp.floorstyle , floorstyle);
2523     assign (rmp.monsterstyle , monsterstyle);
2524     assign (rmp.treasurestyle , treasurestyle);
2525     assign (rmp.layoutstyle , layoutstyle);
2526     assign (rmp.doorstyle , doorstyle);
2527     assign (rmp.decorstyle , decorstyle);
2528     assign (rmp.exitstyle , exitstyle);
2529     assign (rmp.exit_on_final_map, exit_on_final_map);
2530    
2531 root 1.122 rmp.origin_map = origin_map;
2532     rmp.final_map = final_map;
2533     rmp.this_map = this_map;
2534 root 1.146 rmp.xsize = xsize;
2535     rmp.ysize = ysize;
2536 root 1.117 rmp.expand2x = expand2x;
2537     rmp.layoutoptions1 = layoutoptions1;
2538     rmp.layoutoptions2 = layoutoptions2;
2539     rmp.layoutoptions3 = layoutoptions3;
2540     rmp.symmetry = symmetry;
2541     rmp.difficulty = difficulty;
2542     rmp.difficulty_given = difficulty_given;
2543     rmp.difficulty_increase = difficulty_increase;
2544     rmp.dungeon_level = dungeon_level;
2545     rmp.dungeon_depth = dungeon_depth;
2546     rmp.decoroptions = decoroptions;
2547     rmp.orientation = orientation;
2548     rmp.origin_y = origin_y;
2549     rmp.origin_x = origin_x;
2550     rmp.random_seed = random_seed;
2551 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2552 root 1.117 rmp.map_layout_style = map_layout_style;
2553     rmp.treasureoptions = treasureoptions;
2554     rmp.symmetry_used = symmetry_used;
2555     rmp.region = region;
2556 root 1.137 rmp.custom = custom;
2557 root 1.117
2558 root 1.140 RETVAL = self->generate_random_map (&rmp);
2559 root 1.117 }
2560     OUTPUT:
2561     RETVAL
2562    
2563 root 1.19 MODULE = cf PACKAGE = cf::arch
2564 root 1.1
2565 root 1.218 int archetypes_size ()
2566     CODE:
2567     RETVAL = archetypes.size ();
2568     OUTPUT: RETVAL
2569    
2570     archetype *archetypes (U32 index)
2571     CODE:
2572     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2573     OUTPUT: RETVAL
2574 root 1.1
2575 root 1.212 object *instantiate (archetype *arch)
2576     CODE:
2577     RETVAL = arch_to_object (arch);
2578     OUTPUT:
2579     RETVAL
2580    
2581 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2582 root 1.1
2583 root 1.19 MODULE = cf PACKAGE = cf::party
2584 root 1.1
2585 root 1.19 partylist *first ()
2586 root 1.1 PROTOTYPE:
2587 root 1.19 CODE:
2588     RETVAL = get_firstparty ();
2589     OUTPUT: RETVAL
2590 root 1.1
2591 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2592 root 1.1
2593 root 1.19 MODULE = cf PACKAGE = cf::region
2594 root 1.1
2595 root 1.161 void
2596     list ()
2597     PPCODE:
2598     for_all_regions (rgn)
2599     XPUSHs (sv_2mortal (to_sv (rgn)));
2600    
2601 root 1.183 region *find (utf8_string name)
2602 root 1.161 PROTOTYPE: $
2603 root 1.19 CODE:
2604 root 1.161 RETVAL = region::find (name);
2605 root 1.19 OUTPUT: RETVAL
2606 root 1.1
2607 root 1.183 region *find_fuzzy (utf8_string name)
2608 root 1.122 PROTOTYPE: $
2609     CODE:
2610 root 1.161 RETVAL = region::find_fuzzy (name);
2611 root 1.122 OUTPUT: RETVAL
2612    
2613 root 1.186 int specificity (region *rgn)
2614     CODE:
2615     RETVAL = 0;
2616     while (rgn = rgn->parent)
2617     RETVAL++;
2618     OUTPUT: RETVAL
2619    
2620 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2621 root 1.1
2622 root 1.19 MODULE = cf PACKAGE = cf::living
2623 root 1.1
2624 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2625 root 1.1
2626 root 1.76 MODULE = cf PACKAGE = cf::settings
2627    
2628 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2629 root 1.76
2630 root 1.84 MODULE = cf PACKAGE = cf::client
2631 root 1.79
2632 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2633 root 1.79
2634 root 1.84 int invoke (client *ns, int event, ...)
2635 root 1.79 CODE:
2636 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2637 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2638     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2639 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2640 root 1.79 OUTPUT: RETVAL
2641    
2642 root 1.84 SV *registry (client *ns)
2643 root 1.79
2644 root 1.100 void
2645     list ()
2646     PPCODE:
2647     EXTEND (SP, clients.size ());
2648     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2649     PUSHs (sv_2mortal (to_sv (*i)));
2650    
2651 root 1.88 void
2652 root 1.100 client::send_packet (SV *packet)
2653     CODE:
2654     {
2655     STRLEN len;
2656     char *buf = SvPVbyte (packet, len);
2657    
2658     THIS->send_packet (buf, len);
2659     }
2660    
2661 root 1.237 faceidx
2662 root 1.238 client::need_face (utf8_string name, int pri = 0)
2663 root 1.237 CODE:
2664 root 1.238 RETVAL = face_find (name, 0);
2665     if (RETVAL)
2666     {
2667     THIS->send_face (RETVAL, pri);
2668     THIS->flush_fx ();
2669     }
2670     OUTPUT:
2671     RETVAL
2672    
2673     int
2674     client::fx_want (int idx, int value = -1)
2675     CODE:
2676     if (0 < idx && idx < FT_NUM)
2677     {
2678     RETVAL = THIS->fx_want [idx];
2679     if (items > 2)
2680     THIS->fx_want [idx] = value;
2681     }
2682     else
2683     RETVAL = 0;
2684 root 1.237 OUTPUT:
2685     RETVAL
2686    
2687 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2688    
2689     faceidx sound_find (utf8_string name)
2690    
2691 root 1.240 void sound_set (utf8_string str, faceidx face)
2692    
2693     # dire hack
2694     void old_sound_index (int idx, faceidx face)
2695     CODE:
2696     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2697     old_sound_index [idx] = face;
2698    
2699 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2700    
2701 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2702 root 1.176
2703 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2704 root 1.176
2705 root 1.183 faceidx alloc (utf8_string name)
2706 root 1.176 CODE:
2707     {
2708     do
2709     {
2710     RETVAL = faces.size ();
2711 root 1.177 faces.resize (RETVAL + 1);
2712 root 1.176 }
2713     while (!RETVAL); // crude way to leave index 0
2714    
2715     faces [RETVAL].name = name;
2716     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2717    
2718     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2719     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2720     }
2721     OUTPUT: RETVAL
2722    
2723 root 1.227 void set_type (faceidx idx, int value)
2724     ALIAS:
2725     set_type = 0
2726     set_visibility = 1
2727     set_magicmap = 2
2728     set_smooth = 3
2729     set_smoothlevel = 4
2730 root 1.176 CODE:
2731 root 1.229 faceinfo *f = face_info (idx); assert (f);
2732 root 1.227 switch (ix)
2733     {
2734     case 0: f->type = value; break;
2735     case 1: f->visibility = value; break;
2736     case 2: f->magicmap = value; break;
2737     case 3: f->smooth = value; break;
2738     case 4: f->smoothlevel = value; break;
2739     }
2740 root 1.177
2741     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2742 root 1.176 CODE:
2743 root 1.182 {
2744 root 1.231 faceinfo *f = face_info (idx); assert (f);
2745     facedata *d = &(faceset ? f->data64 : f->data32);
2746 root 1.181 sv_to (data, d->data);
2747     STRLEN clen;
2748     char *cdata = SvPVbyte (chksum, clen);
2749 root 1.182 clen = min (CHKSUM_SIZE, clen);
2750    
2751     if (memcmp (d->chksum, cdata, clen))
2752     {
2753     memcpy (d->chksum, cdata, clen);
2754    
2755     // invalidate existing client face info
2756     for_all_clients (ns)
2757     if (ns->faceset == faceset)
2758     {
2759     ns->faces_sent [idx] = false;
2760     ns->force_newmap = true;
2761     }
2762     }
2763     }
2764 root 1.176
2765 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2766     CODE:
2767     facedata *d = face_data (idx, faceset); assert (d);
2768     RETVAL = d->data.size ();
2769     OUTPUT:
2770     RETVAL
2771    
2772     SV *get_chksum (faceidx idx, int faceset = 0)
2773     CODE:
2774     facedata *d = face_data (idx, faceset); assert (d);
2775     RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2776     OUTPUT:
2777     RETVAL
2778    
2779 root 1.177 void invalidate (faceidx idx)
2780     CODE:
2781     for_all_clients (ns)
2782 root 1.182 {
2783     ns->faces_sent [idx] = false;
2784     ns->force_newmap = true;
2785     }
2786 root 1.177
2787     void invalidate_all ()
2788     CODE:
2789     for_all_clients (ns)
2790 root 1.182 {
2791     ns->faces_sent.reset ();
2792     ns->force_newmap = true;
2793     }
2794 root 1.177
2795 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2796    
2797     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2798    
2799     animidx anim_find (utf8_string name)
2800     CODE:
2801     RETVAL = animation::find (name).number;
2802     OUTPUT: RETVAL
2803    
2804     animidx set (utf8_string name, SV *frames, int facings = 1)
2805     CODE:
2806     {
2807     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2808     croak ("frames must be an arrayref");
2809    
2810     AV *av = (AV *)SvRV (frames);
2811    
2812     animation *anim = &animation::find (name);
2813     if (anim->number)
2814     {
2815     anim->resize (av_len (av) + 1);
2816     anim->facings = facings;
2817     }
2818     else
2819     anim = &animation::create (name, av_len (av) + 1, facings);
2820    
2821     for (int i = 0; i < anim->num_animations; ++i)
2822     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2823     }
2824     OUTPUT: RETVAL
2825    
2826     void invalidate_all ()
2827     CODE:
2828     for_all_clients (ns)
2829     ns->anims_sent.reset ();
2830    
2831 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2832    
2833     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2834    
2835     SV *
2836     new (char *klass)
2837     CODE:
2838     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2839     OUTPUT: RETVAL
2840    
2841     void
2842     DESTROY (SV *sv)
2843     CODE:
2844     object_freezer *self;
2845     sv_to (sv, self);
2846     delete self;
2847    
2848     MODULE = cf PACKAGE = cf::object::thawer
2849    
2850     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2851    
2852     SV *
2853     new_from_file (char *klass, octet_string path)
2854     CODE:
2855     object_thawer *f = new object_thawer (path);
2856     if (!*f)
2857     {
2858     delete f;
2859     XSRETURN_UNDEF;
2860     }
2861     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2862     OUTPUT: RETVAL
2863    
2864     void
2865     DESTROY (SV *sv)
2866     CODE:
2867     object_thawer *self;
2868     sv_to (sv, self);
2869     delete self;
2870