ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.328
Committed: Tue Nov 3 22:57:06 2009 UTC (14 years, 7 months ago) by root
Branch: MAIN
Changes since 1.327: +0 -1 lines
Log Message:
copyright removed, as no traces of that code are left, to avoid the doubt of this file containing gpl code

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