ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.315
Committed: Thu Jan 8 03:03:24 2009 UTC (15 years, 4 months ago) by root
Branch: MAIN
Changes since 1.314: +14 -12 lines
Log Message:
connected => shstr, beginning of mapscript

File Contents

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