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