ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.326
Committed: Mon Oct 12 21:27:55 2009 UTC (14 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-2_82
Changes since 1.325: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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