ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.259
Committed: Tue Oct 16 04:09:31 2007 UTC (16 years, 7 months ago) by root
Branch: MAIN
Changes since 1.258: +21 -0 lines
Log Message:
add support for mallinfo, just for me

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