ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.321
Committed: Thu Oct 8 05:04:27 2009 UTC (14 years, 8 months ago) by root
Branch: MAIN
Changes since 1.320: +3 -0 lines
Log Message:
*** empty log message ***

File Contents

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