ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.296
Committed: Sun Aug 31 02:01:41 2008 UTC (15 years, 9 months ago) by root
Branch: MAIN
CVS Tags: rel-2_7
Changes since 1.295: +1 -1 lines
Log Message:
remove FLAG_CLIENT_SENT for good

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