ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.300
Committed: Sun Sep 21 23:21:49 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
Changes since 1.299: +3 -0 lines
Log Message:
*** empty log message ***

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