ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.308
Committed: Mon Nov 24 05:19:59 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
Changes since 1.307: +3 -1 lines
Log Message:
*** empty log message ***

File Contents

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