ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.337
Committed: Thu Nov 12 01:11:52 2009 UTC (14 years, 6 months ago) by root
Branch: MAIN
Changes since 1.336: +73 -20 lines
Log Message:
avoid perl_hv_common etc.

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