ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.303
Committed: Tue Sep 23 04:29:11 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-2_71
Changes since 1.302: +31 -11 lines
Log Message:
*** empty log message ***

File Contents

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