ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.270
Committed: Sat Mar 15 13:52:38 2008 UTC (16 years, 3 months ago) by root
Branch: MAIN
Changes since 1.269: +6 -4 lines
Log Message:
more const correctness and 5.10 gartituous breakage, sigh

File Contents

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