ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.357
Committed: Sun Apr 4 04:17:02 2010 UTC (14 years, 2 months ago) by root
Branch: MAIN
Changes since 1.356: +3 -0 lines
Log Message:
should automate perl constant generation

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