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