ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.263
Committed: Tue Oct 16 14:49:46 2007 UTC (16 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-2_3
Changes since 1.262: +0 -11 lines
Log Message:
pointless

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