ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.286
Committed: Sun May 4 14:12:38 2008 UTC (16 years ago) by root
Branch: MAIN
Changes since 1.285: +30 -20 lines
Log Message:
lotsa

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