ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.314
Committed: Thu Jan 1 20:49:48 2009 UTC (15 years, 4 months ago) by root
Branch: MAIN
Changes since 1.313: +35 -14 lines
Log Message:
slim down perl interface

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