ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.340
Committed: Sun Nov 29 09:41:28 2009 UTC (14 years, 5 months ago) by root
Branch: MAIN
Changes since 1.339: +13 -11 lines
Log Message:
speed is positive inside the server

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