ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.250
Committed: Sat Sep 8 10:14:10 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.249: +1 -1 lines
Log Message:
this is a mess still, needs some redesigning

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     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1555    
1556     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1557 root 1.99
1558 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1559 root 1.117
1560     // random map generator
1561 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1562     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1563    
1564     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1565     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1566     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1567    
1568     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1569     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1570 root 1.195
1571     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1572     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1573     const_iv (GT_MINIMAL)
1574 root 1.238
1575     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1576     const_iv (FT_RSRC) const_iv (FT_NUM)
1577 root 1.1 };
1578    
1579     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1580 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1581 root 1.1
1582     static const struct {
1583     const char *name;
1584 root 1.14 int skip;
1585 root 1.7 IV klass;
1586 root 1.1 IV iv;
1587 root 1.6 } *eiv, event_iv[] = {
1588 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1589 root 1.6 # include "eventinc.h"
1590     # undef def
1591     };
1592    
1593     AV *av = get_av ("cf::EVENT", 1);
1594    
1595     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1596 root 1.7 {
1597     AV *event = newAV ();
1598 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1599 root 1.7 av_push (event, newSViv (eiv->klass));
1600     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1601 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1602 root 1.7 }
1603 root 1.14 }
1604    
1605 root 1.109 void _connect_to_perl ()
1606 root 1.14
1607 root 1.210 void _recalc_want ()
1608    
1609 root 1.47 void _global_reattach ()
1610 root 1.14 CODE:
1611     {
1612     // reattach to all attachable objects in the game.
1613 root 1.128 for_all_clients (ns)
1614     ns->reattach ();
1615 root 1.96
1616 root 1.128 for_all_objects (op)
1617 root 1.109 op->reattach ();
1618 root 1.1 }
1619    
1620 root 1.192 # support function for map-world.ext
1621     void _quantise (SV *data_sv, SV *plt_sv)
1622     CODE:
1623     {
1624     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1625     croak ("_quantise called with invalid agruments");
1626    
1627     plt_sv = SvRV (plt_sv);
1628     SV **plt = AvARRAY (plt_sv);
1629     int plt_count = AvFILL (plt_sv) + 1;
1630    
1631     STRLEN len;
1632     char *data = SvPVbyte (data_sv, len);
1633     char *dst = data;
1634    
1635     while (len >= 3)
1636     {
1637     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1638     {
1639     char *val = SvPVX (*val_sv);
1640    
1641     if (val [0] == data [0]
1642     && val [1] == data [1]
1643     && val [2] == data [2])
1644     {
1645     *dst++ = val [3];
1646     goto next;
1647     }
1648     }
1649    
1650     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1651     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1652     dst - SvPVX (data_sv), len);
1653    
1654     next:
1655     data += 3;
1656     len -= 3;
1657     }
1658    
1659     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1660     }
1661    
1662 root 1.236 void _post_tick ()
1663     CODE:
1664     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1665    
1666     NV till_cede ()
1667     CODE:
1668     RETVAL = coroapi::next_cede - now ();
1669     OUTPUT:
1670     RETVAL
1671    
1672     NV till_tick ()
1673     CODE:
1674     RETVAL = SvNV (sv_next_tick) - now ();
1675     OUTPUT:
1676     RETVAL
1677    
1678 root 1.1 NV floor (NV x)
1679    
1680     NV ceil (NV x)
1681    
1682 root 1.143 NV rndm (...)
1683     CODE:
1684     switch (items)
1685     {
1686     case 0: RETVAL = rndm (); break;
1687     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1688     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1689     default: croak ("cf::rndm requires none, one or two parameters."); break;
1690     }
1691     OUTPUT:
1692     RETVAL
1693    
1694 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1695     CODE:
1696     RETVAL = clamp (value, min_value, max_value);
1697     OUTPUT:
1698     RETVAL
1699    
1700     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1701     CODE:
1702     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1703     OUTPUT:
1704     RETVAL
1705    
1706     void cede_to_tick ()
1707     CODE:
1708     coroapi::cede_to_tick ();
1709    
1710 root 1.5 void server_tick ()
1711 root 1.116 CODE:
1712 root 1.220 NOW = now ();
1713 root 1.116 runtime = SvNVx (sv_runtime);
1714     server_tick ();
1715 root 1.5
1716 root 1.1 void
1717 root 1.198 log_backtrace (utf8_string msg)
1718    
1719     void
1720     LOG (int flags, utf8_string msg)
1721 root 1.1 PROTOTYPE: $$
1722 root 1.198 C_ARGS: flags, "%s", msg
1723 root 1.1
1724 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1725 root 1.1 PROTOTYPE: $$
1726    
1727 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1728 root 1.1 PROTOTYPE: $$
1729    
1730     void
1731     sub_generation_inc ()
1732     CODE:
1733     PL_sub_generation++;
1734    
1735 root 1.183 const_octet_string
1736 root 1.1 mapdir ()
1737     PROTOTYPE:
1738     ALIAS:
1739     mapdir = 0
1740     uniquedir = 1
1741     tmpdir = 2
1742     confdir = 3
1743     localdir = 4
1744     playerdir = 5
1745     datadir = 6
1746     CODE:
1747 root 1.19 switch (ix)
1748     {
1749     case 0: RETVAL = settings.mapdir ; break;
1750     case 1: RETVAL = settings.uniquedir; break;
1751     case 2: RETVAL = settings.tmpdir ; break;
1752     case 3: RETVAL = settings.confdir ; break;
1753     case 4: RETVAL = settings.localdir ; break;
1754     case 5: RETVAL = settings.playerdir; break;
1755     case 6: RETVAL = settings.datadir ; break;
1756     }
1757 root 1.1 OUTPUT: RETVAL
1758    
1759 root 1.120 void abort ()
1760    
1761 root 1.199 void reset_signals ()
1762    
1763 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1764 root 1.144
1765 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1766 root 1.134
1767 root 1.116 void emergency_save ()
1768    
1769 root 1.156 void _exit (int status = EXIT_SUCCESS)
1770    
1771 root 1.149 UV sv_2watcher (SV *w)
1772     CODE:
1773     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1774     OUTPUT:
1775     RETVAL
1776    
1777 root 1.125 #if _POSIX_MEMLOCK
1778    
1779     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1780    
1781     int munlockall ()
1782    
1783     #endif
1784    
1785 root 1.183 int find_animation (utf8_string text)
1786 root 1.1 PROTOTYPE: $
1787    
1788 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1789 root 1.1
1790 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1791 root 1.1
1792     int
1793     exp_to_level (val64 exp)
1794     CODE:
1795     {
1796     int i = 0;
1797    
1798     RETVAL = settings.max_level;
1799    
1800     for (i = 1; i <= settings.max_level; i++)
1801     {
1802     if (levels[i] > exp)
1803     {
1804     RETVAL = i - 1;
1805     break;
1806     }
1807     }
1808     }
1809     OUTPUT: RETVAL
1810    
1811     val64
1812     level_to_min_exp (int level)
1813     CODE:
1814     if (level > settings.max_level)
1815     RETVAL = levels[settings.max_level];
1816     else if (level < 1)
1817     RETVAL = 0;
1818     else
1819     RETVAL = levels[level];
1820     OUTPUT: RETVAL
1821    
1822     SV *
1823     resistance_to_string (int atnr)
1824     CODE:
1825     if (atnr >= 0 && atnr < NROFATTACKS)
1826     RETVAL = newSVpv (resist_plus[atnr], 0);
1827     else
1828     XSRETURN_UNDEF;
1829     OUTPUT: RETVAL
1830    
1831 root 1.162 bool
1832 root 1.183 load_resource_file (octet_string filename)
1833 root 1.162
1834 root 1.97 MODULE = cf PACKAGE = cf::attachable
1835    
1836 root 1.27 int
1837 root 1.97 valid (SV *obj)
1838 root 1.27 CODE:
1839     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1840     OUTPUT:
1841     RETVAL
1842    
1843 root 1.164 void
1844     debug_trace (attachable *obj, bool on = true)
1845     CODE:
1846     obj->flags &= ~attachable::F_DEBUG_TRACE;
1847     if (on)
1848     obj->flags |= attachable::F_DEBUG_TRACE;
1849    
1850 root 1.153 int mortals_size ()
1851     CODE:
1852     RETVAL = attachable::mortals.size ();
1853     OUTPUT: RETVAL
1854    
1855     #object *mortals (U32 index)
1856     # CODE:
1857     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1858     # OUTPUT: RETVAL
1859    
1860 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1861 root 1.115
1862 root 1.101 MODULE = cf PACKAGE = cf::global
1863    
1864     int invoke (SV *klass, int event, ...)
1865     CODE:
1866     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1867     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1868     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1869 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1870 root 1.101 OUTPUT: RETVAL
1871    
1872 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1873    
1874 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1875 root 1.62
1876 root 1.18 int invoke (object *op, int event, ...)
1877     CODE:
1878     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1879 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1880     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1881 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1882 root 1.18 OUTPUT: RETVAL
1883    
1884     SV *registry (object *op)
1885    
1886 root 1.134 int objects_size ()
1887     CODE:
1888     RETVAL = objects.size ();
1889     OUTPUT: RETVAL
1890    
1891     object *objects (U32 index)
1892     CODE:
1893     RETVAL = index < objects.size () ? objects [index] : 0;
1894     OUTPUT: RETVAL
1895    
1896     int actives_size ()
1897     CODE:
1898     RETVAL = actives.size ();
1899     OUTPUT: RETVAL
1900    
1901     object *actives (U32 index)
1902 root 1.57 CODE:
1903 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1904 root 1.57 OUTPUT: RETVAL
1905    
1906 root 1.215 const char *slot_use_name (U32 slot)
1907 root 1.205 ALIAS:
1908 root 1.215 slot_nonuse_name = 1
1909 root 1.205 CODE:
1910     {
1911     if (slot >= NUM_BODY_LOCATIONS)
1912     croak ("body slot index out of range");
1913    
1914     switch (ix)
1915     {
1916 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1917     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1918 root 1.205 }
1919     }
1920     OUTPUT:
1921     RETVAL
1922    
1923 root 1.1 # missing properties
1924    
1925 root 1.54 object *head (object *op)
1926     PROTOTYPE: $
1927     CODE:
1928 root 1.134 RETVAL = op->head_ ();
1929 root 1.54 OUTPUT: RETVAL
1930    
1931 root 1.1 void
1932     inv (object *obj)
1933     PROTOTYPE: $
1934     PPCODE:
1935     {
1936     object *o;
1937     for (o = obj->inv; o; o = o->below)
1938 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1939 root 1.1 }
1940    
1941 root 1.102 void
1942     set_animation (object *op, int idx)
1943     CODE:
1944     SET_ANIMATION (op, idx);
1945    
1946 elmex 1.160 int
1947     num_animations (object *op)
1948     CODE:
1949     RETVAL = NUM_ANIMATIONS (op);
1950     OUTPUT: RETVAL
1951    
1952 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1953     ALIAS:
1954     slot_used = 1
1955     CODE:
1956     {
1957     if (slot >= NUM_BODY_LOCATIONS)
1958     croak ("body slot index out of range");
1959    
1960 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1961 root 1.205
1962     if (items > 2)
1963     if (ix)
1964 root 1.208 op->slot[slot].used = value;
1965     else
1966 root 1.205 op->slot[slot].info = value;
1967     }
1968     OUTPUT:
1969     RETVAL
1970    
1971 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1972 root 1.58
1973     object *find_marked_object (object *op)
1974    
1975 root 1.109 int need_identify (object *obj);
1976 root 1.1
1977     int apply_shop_mat (object *shop_mat, object *op);
1978    
1979 pippijn 1.172 int move_player (object *op, int dir)
1980     CODE:
1981     RETVAL = move_player (op, dir);
1982     OUTPUT:
1983     RETVAL
1984    
1985 root 1.27 int move (object *op, int dir, object *originator = op)
1986     CODE:
1987     RETVAL = move_ob (op, dir, originator);
1988     OUTPUT:
1989     RETVAL
1990 root 1.1
1991 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1992     CODE:
1993     manual_apply (applied, applier, flags);
1994 root 1.1
1995 root 1.74 void apply_below (object *op)
1996     CODE:
1997     player_apply_below (op);
1998 root 1.1
1999 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
2000    
2001 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
2002 root 1.1
2003     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
2004    
2005 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
2006 root 1.1
2007 root 1.116 #//TODO
2008     object *clone_ (object *op, int recursive = 0)
2009 root 1.74 CODE:
2010     if (recursive)
2011     RETVAL = object_create_clone (op);
2012     else
2013     {
2014     RETVAL = object::create ();
2015 root 1.75 op->copy_to (RETVAL);
2016 root 1.74 }
2017     OUTPUT: RETVAL
2018 root 1.1
2019 root 1.74 int pay_item (object *op, object *buyer)
2020     CODE:
2021     RETVAL = pay_for_item (op, buyer);
2022     OUTPUT: RETVAL
2023 root 1.1
2024 root 1.74 int pay_amount (object *op, uint64 amount)
2025     CODE:
2026     RETVAL = pay_for_amount (amount, op);
2027     OUTPUT: RETVAL
2028 root 1.1
2029     void pay_player (object *op, uint64 amount)
2030    
2031 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
2032 root 1.1
2033 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
2034 root 1.1
2035 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
2036     CODE:
2037     do_learn_spell (op, sp, special_prayer);
2038 root 1.1
2039 root 1.74 void forget_spell (object *op, object *sp)
2040     CODE:
2041     do_forget_spell (op, query_name (sp));
2042 root 1.1
2043 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2044 root 1.74 CODE:
2045     RETVAL = check_spell_known (op, spellname);
2046     OUTPUT: RETVAL
2047 root 1.1
2048 root 1.74 int query_money (object *op)
2049 root 1.1 ALIAS: money = 0
2050    
2051 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2052 root 1.1 ALIAS: cost = 0
2053    
2054 root 1.74 void spring_trap (object *op, object *victim)
2055 root 1.1
2056 root 1.74 int check_trigger (object *op, object *cause)
2057 root 1.1
2058 root 1.74 void drop (object *who, object *op)
2059 root 1.1
2060 root 1.74 void pick_up (object *who, object *op)
2061 root 1.1
2062 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
2063 root 1.1
2064 root 1.102 void update_object (object *op, int action)
2065 root 1.1
2066 root 1.183 object *cf_create_object_by_name (utf8_string name)
2067 root 1.1
2068 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2069 root 1.1
2070     void player_lvl_adj (object *who, object *skill = 0)
2071    
2072     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2073    
2074     int calc_skill_exp (object *who, object *op, object *skill);
2075    
2076     void push_button (object *op);
2077    
2078     void use_trigger (object *op);
2079    
2080 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2081 root 1.1
2082     void remove_button_link (object *op);
2083    
2084 elmex 1.232 void handle_apply_yield (object *op);
2085    
2086 root 1.1
2087     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2088    
2089     object *cf_insert_ob_in_ob (object *ob, object *where)
2090    
2091     # no clean way to get an object from an archetype - stupid idiotic
2092     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2093    
2094 root 1.183 object *new (utf8_string archetype = 0)
2095 root 1.1 PROTOTYPE: ;$
2096     CODE:
2097 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2098 root 1.1 OUTPUT:
2099     RETVAL
2100    
2101 root 1.225 object *find_object (U32 tag)
2102    
2103 root 1.218 # TODO: nuke
2104 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2105 root 1.1 PROTOTYPE: $$$$$$
2106     CODE:
2107     {
2108     int unused_type;
2109     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
2110     }
2111    
2112 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
2113 root 1.1
2114 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
2115 root 1.1
2116     object *get_nearest_player (object *ob)
2117     ALIAS: nearest_player = 0
2118     PREINIT:
2119     extern object *get_nearest_player (object *);
2120    
2121     void rangevector (object *ob, object *other, int flags = 0)
2122     PROTOTYPE: $$;$
2123     PPCODE:
2124     {
2125     rv_vector rv;
2126     get_rangevector (ob, other, &rv, flags);
2127     EXTEND (SP, 5);
2128     PUSHs (newSVuv (rv.distance));
2129     PUSHs (newSViv (rv.distance_x));
2130     PUSHs (newSViv (rv.distance_y));
2131     PUSHs (newSViv (rv.direction));
2132     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
2133     }
2134    
2135     bool on_same_map_as (object *ob, object *other)
2136     CODE:
2137     RETVAL = on_same_map (ob, other);
2138     OUTPUT: RETVAL
2139    
2140 root 1.183 const_utf8_string
2141 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2142 root 1.1 CODE:
2143 root 1.58 RETVAL = query_base_name (op, plural);
2144 root 1.1 OUTPUT: RETVAL
2145    
2146 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
2147    
2148 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2149    
2150     player *player (object *op)
2151     CODE:
2152     RETVAL = op->contr;
2153     OUTPUT: RETVAL
2154    
2155 root 1.105 void check_score (object *op)
2156    
2157 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2158 root 1.120 CODE:
2159     new_draw_info (flags, 0, op, txt);
2160 root 1.1
2161     void kill_player (object *op)
2162    
2163 root 1.58 void esrv_update_item (object *op, int what, object *item)
2164     C_ARGS: what, op, item
2165    
2166 root 1.183 int command_summon (object *op, utf8_string params)
2167 root 1.67
2168 root 1.183 int command_arrest (object *op, utf8_string params)
2169 root 1.67
2170 root 1.66
2171 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2172 root 1.1
2173 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2174 root 1.62
2175 root 1.18 int invoke (player *pl, int event, ...)
2176     CODE:
2177     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2178 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2179     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2180 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2181 root 1.18 OUTPUT: RETVAL
2182    
2183 root 1.12 SV *registry (player *pl)
2184 root 1.1
2185 root 1.102 void
2186     save_stats (player *pl)
2187     CODE:
2188     pl->ob->stats.hp = pl->ob->stats.maxhp;
2189     pl->ob->stats.sp = pl->ob->stats.maxsp;
2190     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2191     pl->orig_stats = pl->ob->stats;
2192    
2193 root 1.217 void clear_los (player *pl)
2194    
2195 root 1.1 void cf_player_move (player *pl, int dir)
2196    
2197     bool
2198     cell_visible (player *pl, int dx, int dy)
2199     CODE:
2200 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2201     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2202 root 1.1 OUTPUT:
2203     RETVAL
2204    
2205 root 1.4 void
2206 root 1.1 send (player *pl, SV *packet)
2207     CODE:
2208     {
2209     STRLEN len;
2210     char *buf = SvPVbyte (packet, len);
2211    
2212 root 1.100 if (pl->ns)
2213     pl->ns->send_packet (buf, len);
2214 root 1.1 }
2215    
2216     int
2217     listening (player *pl, int new_value = -1)
2218     CODE:
2219     RETVAL = pl->listening;
2220     if (new_value >= 0)
2221     pl->listening = new_value;
2222     OUTPUT:
2223     RETVAL
2224    
2225 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2226 root 1.45 PROTOTYPE: $;$$$
2227 root 1.1 PPCODE:
2228 root 1.45 if (GIMME_V != G_VOID)
2229     {
2230     EXTEND (SP, 3);
2231     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2232     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2233     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2234     }
2235 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2236     if (x) sv_to (x, pl->bed_x);
2237     if (y) sv_to (y, pl->bed_y);
2238 root 1.1
2239     void
2240     list ()
2241     PPCODE:
2242 root 1.128 for_all_players (pl)
2243 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2244 root 1.1
2245    
2246     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2247    
2248 root 1.61 int invoke (maptile *map, int event, ...)
2249 root 1.18 CODE:
2250     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2251 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2252     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2253 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2254 root 1.25 OUTPUT: RETVAL
2255 root 1.18
2256 root 1.61 SV *registry (maptile *map)
2257 root 1.12
2258 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2259 root 1.1
2260 root 1.116 void
2261     maptile::instantiate ()
2262    
2263     maptile *new ()
2264 root 1.1 PROTOTYPE:
2265     CODE:
2266 root 1.116 RETVAL = new maptile;
2267 root 1.1 OUTPUT:
2268     RETVAL
2269    
2270 root 1.116 void
2271 root 1.117 maptile::players ()
2272     PPCODE:
2273     if (GIMME_V == G_SCALAR)
2274 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2275 root 1.117 else if (GIMME_V == G_ARRAY)
2276     {
2277     EXTEND (SP, THIS->players);
2278     for_all_players (pl)
2279     if (pl->ob && pl->ob->map == THIS)
2280 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2281 root 1.117 }
2282    
2283 root 1.156 void
2284 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2285 root 1.156 CODE:
2286     {
2287 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2288     croak ("maptile::add_underlay: palette must be arrayref");
2289 root 1.156
2290 root 1.168 palette = SvRV (palette);
2291 root 1.156
2292 root 1.168 STRLEN idxlen;
2293     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2294 root 1.156
2295 root 1.168 for (int x = 0; x < THIS->width; ++x)
2296     for (int y = 0; y < THIS->height; ++y)
2297     {
2298     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2299     if (op->flag [FLAG_IS_FLOOR])
2300     goto skip_space;
2301    
2302     {
2303     int offs = offset + y * stride + x;
2304     if (IN_RANGE_EXC (offs, 0, idxlen))
2305     {
2306     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2307     {
2308     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2309     ob->flag [FLAG_NO_MAP_SAVE] = true;
2310     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2311 root 1.200
2312     if (ob->randomitems)
2313     {
2314 root 1.203 if (!ob->above)
2315     {
2316     ob->create_treasure (ob->randomitems);
2317    
2318     for (object *op = ob->above; op; op = op->above)
2319     op->flag [FLAG_NO_MAP_SAVE] = true;
2320     }
2321    
2322 root 1.200 ob->randomitems = 0;
2323     }
2324 root 1.168 }
2325     }
2326     }
2327 root 1.156
2328 root 1.168 skip_space: ;
2329     }
2330     }
2331    
2332     void
2333     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2334     CODE:
2335     {
2336     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2337     croak ("maptile::set_regiondata: palette must be arrayref");
2338    
2339     palette = SvRV (palette);
2340    
2341     STRLEN idxlen;
2342     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2343    
2344 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2345 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2346    
2347     for (int i = av_len ((AV *)palette) + 1; i--; )
2348 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2349 root 1.168
2350     for (int y = 0; y < THIS->height; ++y)
2351     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2352    
2353     sfree (THIS->regions, THIS->size ());
2354 root 1.230 delete [] THIS->regionmap;
2355 root 1.168
2356     THIS->regions = regions;
2357 root 1.156 THIS->regionmap = regionmap;
2358     }
2359    
2360 root 1.193 void
2361     maptile::create_region_treasure ()
2362     CODE:
2363     {
2364     object *op = object::create ();
2365     op->type = FLOOR;
2366     op->map = THIS;
2367    
2368     for (int x = 0; x < THIS->width; ++x)
2369     for (int y = 0; y < THIS->height; ++y)
2370     {
2371     region *rgn = THIS->region (x, y);
2372    
2373     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2374     if (rgn->treasure && rndm () < rgn->treasure_density)
2375     {
2376     op->x = x;
2377     op->y = y;
2378     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2379     }
2380     }
2381    
2382     op->destroy ();
2383     }
2384    
2385 root 1.74 int out_of_map (maptile *map, int x, int y)
2386    
2387 root 1.29 void
2388 root 1.61 trigger (maptile *map, long connection, bool state = true)
2389 root 1.29 CODE:
2390     activate_connection (map, connection, state);
2391    
2392     void
2393 root 1.61 get_connection (maptile *map, long connection)
2394 root 1.29 PPCODE:
2395     oblinkpt *obp = get_connection_links (map, connection);
2396     if (obp)
2397     for (objectlink *ol = obp->link; ol; ol = ol->next)
2398 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2399 root 1.29
2400 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2401 root 1.1
2402 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2403 root 1.1
2404 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2405 root 1.1 C_ARGS: str, map, nx, ny
2406    
2407     void
2408 root 1.140 get_map_flags (maptile *map, int x, int y)
2409 root 1.1 PPCODE:
2410     {
2411 root 1.61 maptile *nmap = 0;
2412 root 1.1 I16 nx = 0, ny = 0;
2413 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2414 root 1.1
2415     EXTEND (SP, 4);
2416     PUSHs (sv_2mortal (newSViv (flags)));
2417    
2418     if (GIMME_V == G_ARRAY)
2419     {
2420     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2421     PUSHs (sv_2mortal (newSViv (nx)));
2422     PUSHs (sv_2mortal (newSViv (ny)));
2423     }
2424     }
2425    
2426     void
2427 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2428 root 1.1 PROTOTYPE: $$$
2429     PPCODE:
2430     {
2431     object *o;
2432 root 1.61 maptile *nmap = 0;
2433 root 1.1 I16 nx, ny;
2434    
2435 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2436 root 1.1
2437     if (nmap)
2438     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2439     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2440     }
2441    
2442     SV *
2443 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2444 root 1.1 PROTOTYPE: $$$
2445     ALIAS:
2446     top_at = 1
2447     flags_at = 2
2448     light_at = 3
2449     move_block_at = 4
2450     move_slow_at = 5
2451     move_on_at = 6
2452     move_off_at = 7
2453     INIT:
2454 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2455 root 1.1 CODE:
2456     switch (ix)
2457     {
2458     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2459     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2460     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2461     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2462     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2463     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2464     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2465     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2466     }
2467 root 1.122 OUTPUT: RETVAL
2468 root 1.1
2469 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2470    
2471     void fix_walls_around (maptile *map, int x, int y)
2472 root 1.1
2473 root 1.117 # worst xs function of my life
2474 root 1.140 bool
2475 root 1.117 _create_random_map (\
2476 root 1.140 maptile *self,\
2477 root 1.183 utf8_string wallstyle,\
2478     utf8_string wall_name,\
2479     utf8_string floorstyle,\
2480     utf8_string monsterstyle,\
2481     utf8_string treasurestyle,\
2482     utf8_string layoutstyle,\
2483     utf8_string doorstyle,\
2484     utf8_string decorstyle,\
2485     utf8_string origin_map,\
2486     utf8_string final_map,\
2487     utf8_string exitstyle,\
2488     utf8_string this_map,\
2489     utf8_string exit_on_final_map,\
2490 root 1.146 int xsize,\
2491     int ysize,\
2492 root 1.117 int expand2x,\
2493     int layoutoptions1,\
2494     int layoutoptions2,\
2495     int layoutoptions3,\
2496     int symmetry,\
2497     int difficulty,\
2498     int difficulty_given,\
2499     float difficulty_increase,\
2500     int dungeon_level,\
2501     int dungeon_depth,\
2502     int decoroptions,\
2503     int orientation,\
2504     int origin_y,\
2505     int origin_x,\
2506 root 1.146 U32 random_seed,\
2507 root 1.117 val64 total_map_hp,\
2508     int map_layout_style,\
2509     int treasureoptions,\
2510     int symmetry_used,\
2511 root 1.137 region *region,\
2512 root 1.183 utf8_string custom\
2513 root 1.117 )
2514     CODE:
2515     {
2516     random_map_params rmp;
2517    
2518     assign (rmp.wallstyle , wallstyle);
2519     assign (rmp.wall_name , wall_name);
2520     assign (rmp.floorstyle , floorstyle);
2521     assign (rmp.monsterstyle , monsterstyle);
2522     assign (rmp.treasurestyle , treasurestyle);
2523     assign (rmp.layoutstyle , layoutstyle);
2524     assign (rmp.doorstyle , doorstyle);
2525     assign (rmp.decorstyle , decorstyle);
2526     assign (rmp.exitstyle , exitstyle);
2527     assign (rmp.exit_on_final_map, exit_on_final_map);
2528    
2529 root 1.122 rmp.origin_map = origin_map;
2530     rmp.final_map = final_map;
2531     rmp.this_map = this_map;
2532 root 1.146 rmp.xsize = xsize;
2533     rmp.ysize = ysize;
2534 root 1.117 rmp.expand2x = expand2x;
2535     rmp.layoutoptions1 = layoutoptions1;
2536     rmp.layoutoptions2 = layoutoptions2;
2537     rmp.layoutoptions3 = layoutoptions3;
2538     rmp.symmetry = symmetry;
2539     rmp.difficulty = difficulty;
2540     rmp.difficulty_given = difficulty_given;
2541     rmp.difficulty_increase = difficulty_increase;
2542     rmp.dungeon_level = dungeon_level;
2543     rmp.dungeon_depth = dungeon_depth;
2544     rmp.decoroptions = decoroptions;
2545     rmp.orientation = orientation;
2546     rmp.origin_y = origin_y;
2547     rmp.origin_x = origin_x;
2548     rmp.random_seed = random_seed;
2549 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2550 root 1.117 rmp.map_layout_style = map_layout_style;
2551     rmp.treasureoptions = treasureoptions;
2552     rmp.symmetry_used = symmetry_used;
2553     rmp.region = region;
2554 root 1.137 rmp.custom = custom;
2555 root 1.117
2556 root 1.140 RETVAL = self->generate_random_map (&rmp);
2557 root 1.117 }
2558     OUTPUT:
2559     RETVAL
2560    
2561 root 1.19 MODULE = cf PACKAGE = cf::arch
2562 root 1.1
2563 root 1.218 int archetypes_size ()
2564     CODE:
2565     RETVAL = archetypes.size ();
2566     OUTPUT: RETVAL
2567    
2568     archetype *archetypes (U32 index)
2569     CODE:
2570     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2571     OUTPUT: RETVAL
2572 root 1.1
2573 root 1.212 object *instantiate (archetype *arch)
2574     CODE:
2575     RETVAL = arch_to_object (arch);
2576     OUTPUT:
2577     RETVAL
2578    
2579 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2580 root 1.1
2581 root 1.19 MODULE = cf PACKAGE = cf::party
2582 root 1.1
2583 root 1.19 partylist *first ()
2584 root 1.1 PROTOTYPE:
2585 root 1.19 CODE:
2586     RETVAL = get_firstparty ();
2587     OUTPUT: RETVAL
2588 root 1.1
2589 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2590 root 1.1
2591 root 1.19 MODULE = cf PACKAGE = cf::region
2592 root 1.1
2593 root 1.161 void
2594     list ()
2595     PPCODE:
2596     for_all_regions (rgn)
2597     XPUSHs (sv_2mortal (to_sv (rgn)));
2598    
2599 root 1.183 region *find (utf8_string name)
2600 root 1.161 PROTOTYPE: $
2601 root 1.19 CODE:
2602 root 1.161 RETVAL = region::find (name);
2603 root 1.19 OUTPUT: RETVAL
2604 root 1.1
2605 root 1.183 region *find_fuzzy (utf8_string name)
2606 root 1.122 PROTOTYPE: $
2607     CODE:
2608 root 1.161 RETVAL = region::find_fuzzy (name);
2609 root 1.122 OUTPUT: RETVAL
2610    
2611 root 1.186 int specificity (region *rgn)
2612     CODE:
2613     RETVAL = 0;
2614     while (rgn = rgn->parent)
2615     RETVAL++;
2616     OUTPUT: RETVAL
2617    
2618 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2619 root 1.1
2620 root 1.19 MODULE = cf PACKAGE = cf::living
2621 root 1.1
2622 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2623 root 1.1
2624 root 1.76 MODULE = cf PACKAGE = cf::settings
2625    
2626 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2627 root 1.76
2628 root 1.84 MODULE = cf PACKAGE = cf::client
2629 root 1.79
2630 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2631 root 1.79
2632 root 1.84 int invoke (client *ns, int event, ...)
2633 root 1.79 CODE:
2634 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2635 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2636     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2637 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2638 root 1.79 OUTPUT: RETVAL
2639    
2640 root 1.84 SV *registry (client *ns)
2641 root 1.79
2642 root 1.100 void
2643     list ()
2644     PPCODE:
2645     EXTEND (SP, clients.size ());
2646     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2647     PUSHs (sv_2mortal (to_sv (*i)));
2648    
2649 root 1.88 void
2650 root 1.100 client::send_packet (SV *packet)
2651     CODE:
2652     {
2653     STRLEN len;
2654     char *buf = SvPVbyte (packet, len);
2655    
2656     THIS->send_packet (buf, len);
2657     }
2658    
2659 root 1.237 faceidx
2660 root 1.238 client::need_face (utf8_string name, int pri = 0)
2661 root 1.237 CODE:
2662 root 1.238 RETVAL = face_find (name, 0);
2663     if (RETVAL)
2664     {
2665     THIS->send_face (RETVAL, pri);
2666     THIS->flush_fx ();
2667     }
2668     OUTPUT:
2669     RETVAL
2670    
2671     int
2672     client::fx_want (int idx, int value = -1)
2673     CODE:
2674     if (0 < idx && idx < FT_NUM)
2675     {
2676     RETVAL = THIS->fx_want [idx];
2677     if (items > 2)
2678     THIS->fx_want [idx] = value;
2679     }
2680     else
2681     RETVAL = 0;
2682 root 1.237 OUTPUT:
2683     RETVAL
2684    
2685 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2686    
2687     faceidx sound_find (utf8_string name)
2688    
2689 root 1.240 void sound_set (utf8_string str, faceidx face)
2690    
2691     # dire hack
2692     void old_sound_index (int idx, faceidx face)
2693     CODE:
2694     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2695     old_sound_index [idx] = face;
2696    
2697 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2698    
2699 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2700 root 1.176
2701 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2702 root 1.176
2703 root 1.183 faceidx alloc (utf8_string name)
2704 root 1.176 CODE:
2705     {
2706     do
2707     {
2708     RETVAL = faces.size ();
2709 root 1.177 faces.resize (RETVAL + 1);
2710 root 1.176 }
2711     while (!RETVAL); // crude way to leave index 0
2712    
2713     faces [RETVAL].name = name;
2714     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2715    
2716     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2717     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2718     }
2719     OUTPUT: RETVAL
2720    
2721 root 1.227 void set_type (faceidx idx, int value)
2722     ALIAS:
2723     set_type = 0
2724     set_visibility = 1
2725     set_magicmap = 2
2726     set_smooth = 3
2727     set_smoothlevel = 4
2728 root 1.176 CODE:
2729 root 1.229 faceinfo *f = face_info (idx); assert (f);
2730 root 1.227 switch (ix)
2731     {
2732     case 0: f->type = value; break;
2733     case 1: f->visibility = value; break;
2734     case 2: f->magicmap = value; break;
2735     case 3: f->smooth = value; break;
2736     case 4: f->smoothlevel = value; break;
2737     }
2738 root 1.177
2739     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2740 root 1.176 CODE:
2741 root 1.182 {
2742 root 1.231 faceinfo *f = face_info (idx); assert (f);
2743     facedata *d = &(faceset ? f->data64 : f->data32);
2744 root 1.181 sv_to (data, d->data);
2745     STRLEN clen;
2746     char *cdata = SvPVbyte (chksum, clen);
2747 root 1.182 clen = min (CHKSUM_SIZE, clen);
2748    
2749     if (memcmp (d->chksum, cdata, clen))
2750     {
2751     memcpy (d->chksum, cdata, clen);
2752    
2753     // invalidate existing client face info
2754     for_all_clients (ns)
2755     if (ns->faceset == faceset)
2756     {
2757     ns->faces_sent [idx] = false;
2758     ns->force_newmap = true;
2759     }
2760     }
2761     }
2762 root 1.176
2763 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2764     CODE:
2765     facedata *d = face_data (idx, faceset); assert (d);
2766     RETVAL = d->data.size ();
2767     OUTPUT:
2768     RETVAL
2769    
2770     SV *get_chksum (faceidx idx, int faceset = 0)
2771     CODE:
2772     facedata *d = face_data (idx, faceset); assert (d);
2773     RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2774     OUTPUT:
2775     RETVAL
2776    
2777 root 1.177 void invalidate (faceidx idx)
2778     CODE:
2779     for_all_clients (ns)
2780 root 1.182 {
2781     ns->faces_sent [idx] = false;
2782     ns->force_newmap = true;
2783     }
2784 root 1.177
2785     void invalidate_all ()
2786     CODE:
2787     for_all_clients (ns)
2788 root 1.182 {
2789     ns->faces_sent.reset ();
2790     ns->force_newmap = true;
2791     }
2792 root 1.177
2793 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2794    
2795     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2796    
2797     animidx anim_find (utf8_string name)
2798     CODE:
2799     RETVAL = animation::find (name).number;
2800     OUTPUT: RETVAL
2801    
2802     animidx set (utf8_string name, SV *frames, int facings = 1)
2803     CODE:
2804     {
2805     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2806     croak ("frames must be an arrayref");
2807    
2808     AV *av = (AV *)SvRV (frames);
2809    
2810     animation *anim = &animation::find (name);
2811     if (anim->number)
2812     {
2813     anim->resize (av_len (av) + 1);
2814     anim->facings = facings;
2815     }
2816     else
2817     anim = &animation::create (name, av_len (av) + 1, facings);
2818    
2819     for (int i = 0; i < anim->num_animations; ++i)
2820     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2821     }
2822     OUTPUT: RETVAL
2823    
2824     void invalidate_all ()
2825     CODE:
2826     for_all_clients (ns)
2827     ns->anims_sent.reset ();
2828    
2829 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2830    
2831     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2832    
2833     SV *
2834     new (char *klass)
2835     CODE:
2836     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2837     OUTPUT: RETVAL
2838    
2839     void
2840     DESTROY (SV *sv)
2841     CODE:
2842     object_freezer *self;
2843     sv_to (sv, self);
2844     delete self;
2845    
2846     MODULE = cf PACKAGE = cf::object::thawer
2847    
2848     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2849    
2850     SV *
2851     new_from_file (char *klass, octet_string path)
2852     CODE:
2853     object_thawer *f = new object_thawer (path);
2854     if (!*f)
2855     {
2856     delete f;
2857     XSRETURN_UNDEF;
2858     }
2859     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2860     OUTPUT: RETVAL
2861    
2862     void
2863     DESTROY (SV *sv)
2864     CODE:
2865     object_thawer *self;
2866     sv_to (sv, self);
2867     delete self;
2868