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