ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.292
Committed: Tue Jul 29 02:00:55 2008 UTC (15 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-2_61
Changes since 1.291: +1 -0 lines
Log Message:
4.3

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