ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.304
Committed: Wed Oct 1 05:50:19 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
Changes since 1.303: +18 -6 lines
Log Message:
*** empty log message ***

File Contents

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