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