ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.302
Committed: Mon Sep 22 23:57:48 2008 UTC (15 years, 8 months ago) by root
Branch: MAIN
Changes since 1.301: +0 -2 lines
Log Message:
*** empty log message ***

File Contents

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