ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.299
Committed: Fri Sep 19 01:39:45 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
Changes since 1.298: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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