ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.267
Committed: Mon Dec 17 08:03:22 2007 UTC (16 years, 5 months ago) by root
Branch: MAIN
Changes since 1.266: +12 -2 lines
Log Message:
- separate internal (undefined type) and client-exported (else)
  resources.
- new %cf::RESOURCE hash for internal resources
- move jeweler.yaml to archetype ("resource") data
- support resource data filters and implement yaml2json
  (this reduced loading time for the jeweler data by a factor of 1000 :).
- clean up Jeweler.pm a bit.

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