ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.332
Committed: Fri Nov 6 13:21:20 2009 UTC (14 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-2_90
Changes since 1.331: +2 -0 lines
Log Message:
unused

File Contents

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