ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.313
Committed: Tue Dec 23 18:52:58 2008 UTC (15 years, 5 months ago) by pippijn
Branch: MAIN
CVS Tags: rel-2_74
Changes since 1.312: +1 -1 lines
Log Message:
thats => that's
some more typo fixes in maps (i => I, missing commas, bad casing, etc.)

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