ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.329
Committed: Wed Nov 4 17:24:00 2009 UTC (14 years, 7 months ago) by root
Branch: MAIN
Changes since 1.328: +3 -0 lines
Log Message:
interim checkin, new spell

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.329
2228     if (RETVAL->destroyed ())
2229     RETVAL = 0;
2230 root 1.1 }
2231    
2232 root 1.284 shstr
2233     object::kv_get (shstr key)
2234 root 1.1
2235 root 1.284 void
2236     object::kv_del (shstr key)
2237    
2238     void
2239     object::kv_set (shstr key, shstr value)
2240 root 1.1
2241     object *get_nearest_player (object *ob)
2242     ALIAS: nearest_player = 0
2243     PREINIT:
2244     extern object *get_nearest_player (object *);
2245    
2246     void rangevector (object *ob, object *other, int flags = 0)
2247     PROTOTYPE: $$;$
2248     PPCODE:
2249     {
2250     rv_vector rv;
2251 root 1.291
2252     PUTBACK;
2253 root 1.1 get_rangevector (ob, other, &rv, flags);
2254 root 1.291 SPAGAIN;
2255    
2256 root 1.1 EXTEND (SP, 5);
2257     PUSHs (newSVuv (rv.distance));
2258     PUSHs (newSViv (rv.distance_x));
2259     PUSHs (newSViv (rv.distance_y));
2260     PUSHs (newSViv (rv.direction));
2261 root 1.257 PUSHs (to_sv (rv.part));
2262 root 1.1 }
2263    
2264     bool on_same_map_as (object *ob, object *other)
2265     CODE:
2266     RETVAL = on_same_map (ob, other);
2267     OUTPUT: RETVAL
2268    
2269 root 1.183 const_utf8_string
2270 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2271 root 1.1 CODE:
2272 root 1.58 RETVAL = query_base_name (op, plural);
2273 root 1.1 OUTPUT: RETVAL
2274    
2275 root 1.256 # return the tail of an object, excluding itself
2276     void
2277     tail (object *op)
2278     PPCODE:
2279     while ((op = op->more))
2280     XPUSHs (sv_2mortal (to_sv (op)));
2281    
2282 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2283    
2284     player *player (object *op)
2285     CODE:
2286     RETVAL = op->contr;
2287     OUTPUT: RETVAL
2288    
2289 root 1.257 bool move_player (object *op, int dir)
2290    
2291 root 1.105 void check_score (object *op)
2292    
2293 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2294 root 1.120 CODE:
2295     new_draw_info (flags, 0, op, txt);
2296 root 1.1
2297     void kill_player (object *op)
2298    
2299 root 1.257 void esrv_send_item (object *pl, object *item)
2300    
2301     void esrv_update_item (object *pl, int what, object *item)
2302     C_ARGS: what, pl, item
2303    
2304     void esrv_del_item (object *pl, int tag)
2305     C_ARGS: pl->contr, tag
2306 root 1.58
2307 root 1.183 int command_summon (object *op, utf8_string params)
2308 root 1.67
2309 root 1.183 int command_arrest (object *op, utf8_string params)
2310 root 1.67
2311 root 1.66
2312 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2313 root 1.1
2314 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2315 root 1.62
2316 root 1.18 int invoke (player *pl, int event, ...)
2317     CODE:
2318     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2319 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2320     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2321 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2322 root 1.18 OUTPUT: RETVAL
2323    
2324 root 1.12 SV *registry (player *pl)
2325 root 1.1
2326 root 1.102 void
2327     save_stats (player *pl)
2328     CODE:
2329     pl->ob->stats.hp = pl->ob->stats.maxhp;
2330     pl->ob->stats.sp = pl->ob->stats.maxsp;
2331     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2332     pl->orig_stats = pl->ob->stats;
2333    
2334 root 1.307 # should only be temporary
2335 elmex 1.306 void esrv_new_player (player *pl)
2336    
2337 root 1.310 #d# TODO: replace by blocked_los accessor, fix code using this
2338 root 1.1 bool
2339     cell_visible (player *pl, int dx, int dy)
2340     CODE:
2341 root 1.310 RETVAL = pl->blocked_los (dx, dy) != LOS_BLOCKED;
2342 root 1.1 OUTPUT:
2343     RETVAL
2344    
2345 root 1.4 void
2346 root 1.1 send (player *pl, SV *packet)
2347     CODE:
2348     {
2349     STRLEN len;
2350     char *buf = SvPVbyte (packet, len);
2351    
2352 root 1.258 if (len > MAXSOCKBUF)
2353     pl->failmsg ("[packet too long for client]");
2354     else if (pl->ns)
2355 root 1.100 pl->ns->send_packet (buf, len);
2356 root 1.1 }
2357    
2358 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2359 root 1.45 PROTOTYPE: $;$$$
2360 root 1.1 PPCODE:
2361 root 1.45 if (GIMME_V != G_VOID)
2362     {
2363     EXTEND (SP, 3);
2364     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2365     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2366     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2367     }
2368 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2369     if (x) sv_to (x, pl->bed_x);
2370     if (y) sv_to (y, pl->bed_y);
2371 root 1.1
2372     void
2373     list ()
2374     PPCODE:
2375 root 1.128 for_all_players (pl)
2376 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2377 root 1.1
2378    
2379     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2380    
2381 root 1.61 int invoke (maptile *map, int event, ...)
2382 root 1.18 CODE:
2383     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2384 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2385     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2386 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2387 root 1.25 OUTPUT: RETVAL
2388 root 1.18
2389 root 1.61 SV *registry (maptile *map)
2390 root 1.12
2391 root 1.255 void
2392     find_tagged_objects (maptile *map, utf8_string tag = 0)
2393     PPCODE:
2394     {
2395     if (!map->spaces)
2396     XSRETURN_EMPTY;
2397    
2398     if (tag)
2399     {
2400     shstr_cmp tag_ (tag);
2401    
2402     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2403     for (object *op = ms->bot; op; op = op->above)
2404     if (op->tag == tag_)
2405     XPUSHs (sv_2mortal (to_sv (op)));
2406     }
2407     else
2408     {
2409     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2410     for (object *op = ms->bot; op; op = op->above)
2411     if (op->tag)
2412     XPUSHs (sv_2mortal (to_sv (op)));
2413     }
2414     }
2415    
2416 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2417 root 1.1
2418 root 1.116 void
2419 root 1.312 adjust_daylight ()
2420     CODE:
2421     maptile::adjust_daylight ();
2422    
2423 root 1.318 int
2424     outdoor_darkness (int darkness = 0)
2425     CODE:
2426     RETVAL = maptile::outdoor_darkness;
2427     if (items)
2428     maptile::outdoor_darkness = darkness;
2429     OUTPUT:
2430     RETVAL
2431    
2432 root 1.312 void
2433 root 1.116 maptile::instantiate ()
2434    
2435     maptile *new ()
2436 root 1.1 PROTOTYPE:
2437     CODE:
2438 root 1.116 RETVAL = new maptile;
2439 root 1.1 OUTPUT:
2440     RETVAL
2441    
2442 root 1.116 void
2443 root 1.117 maptile::players ()
2444     PPCODE:
2445     if (GIMME_V == G_SCALAR)
2446 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2447 root 1.117 else if (GIMME_V == G_ARRAY)
2448     {
2449     EXTEND (SP, THIS->players);
2450     for_all_players (pl)
2451     if (pl->ob && pl->ob->map == THIS)
2452 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2453 root 1.117 }
2454    
2455 root 1.156 void
2456 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2457 root 1.156 CODE:
2458     {
2459 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2460     croak ("maptile::add_underlay: palette must be arrayref");
2461 root 1.156
2462 root 1.168 palette = SvRV (palette);
2463 root 1.156
2464 root 1.168 STRLEN idxlen;
2465     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2466 root 1.156
2467 root 1.168 for (int x = 0; x < THIS->width; ++x)
2468     for (int y = 0; y < THIS->height; ++y)
2469     {
2470     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2471     if (op->flag [FLAG_IS_FLOOR])
2472     goto skip_space;
2473    
2474     {
2475     int offs = offset + y * stride + x;
2476     if (IN_RANGE_EXC (offs, 0, idxlen))
2477     {
2478     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2479     {
2480     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2481     ob->flag [FLAG_NO_MAP_SAVE] = true;
2482     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2483 root 1.200
2484     if (ob->randomitems)
2485     {
2486 root 1.203 if (!ob->above)
2487     {
2488     ob->create_treasure (ob->randomitems);
2489    
2490     for (object *op = ob->above; op; op = op->above)
2491     op->flag [FLAG_NO_MAP_SAVE] = true;
2492     }
2493    
2494 root 1.200 ob->randomitems = 0;
2495     }
2496 root 1.168 }
2497     }
2498     }
2499 root 1.156
2500 root 1.168 skip_space: ;
2501     }
2502     }
2503    
2504     void
2505     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2506     CODE:
2507     {
2508     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2509     croak ("maptile::set_regiondata: palette must be arrayref");
2510    
2511     palette = SvRV (palette);
2512    
2513     STRLEN idxlen;
2514     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2515    
2516 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2517 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2518    
2519     for (int i = av_len ((AV *)palette) + 1; i--; )
2520 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2521 root 1.168
2522     for (int y = 0; y < THIS->height; ++y)
2523     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2524    
2525     sfree (THIS->regions, THIS->size ());
2526 root 1.230 delete [] THIS->regionmap;
2527 root 1.168
2528     THIS->regions = regions;
2529 root 1.156 THIS->regionmap = regionmap;
2530     }
2531    
2532 root 1.193 void
2533     maptile::create_region_treasure ()
2534     CODE:
2535     for (int x = 0; x < THIS->width; ++x)
2536     for (int y = 0; y < THIS->height; ++y)
2537     {
2538     region *rgn = THIS->region (x, y);
2539    
2540     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2541 root 1.301 if (object *op = THIS->at (x, y).top)
2542     if (rgn->treasure && rndm () < rgn->treasure_density)
2543 root 1.193 create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2544     }
2545    
2546 root 1.74 int out_of_map (maptile *map, int x, int y)
2547    
2548 root 1.29 void
2549 root 1.315 find_link (maptile *map, shstr_tmp connection)
2550 root 1.29 PPCODE:
2551 root 1.315 if (oblinkpt *obp = map->find_link (connection))
2552 root 1.29 for (objectlink *ol = obp->link; ol; ol = ol->next)
2553 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2554 root 1.1
2555     void
2556 root 1.140 get_map_flags (maptile *map, int x, int y)
2557 root 1.1 PPCODE:
2558     {
2559 root 1.61 maptile *nmap = 0;
2560 root 1.1 I16 nx = 0, ny = 0;
2561 root 1.291
2562     PUTBACK;
2563 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2564 root 1.291 SPAGAIN;
2565 root 1.1
2566     EXTEND (SP, 4);
2567     PUSHs (sv_2mortal (newSViv (flags)));
2568    
2569     if (GIMME_V == G_ARRAY)
2570     {
2571 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2572 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2573     PUSHs (sv_2mortal (newSViv (ny)));
2574     }
2575     }
2576    
2577 root 1.293 mapspace *
2578     ms (maptile *map, unsigned int x, unsigned int y)
2579     PROTOTYPE: $$$
2580     CODE:
2581     {
2582     maptile *nmap = 0;
2583     I16 nx, ny;
2584    
2585     PUTBACK;
2586     get_map_flags (map, &nmap, x, y, &nx, &ny);
2587     SPAGAIN;
2588    
2589     if (!nmap)
2590     XSRETURN_UNDEF;
2591    
2592     RETVAL = &nmap->at (nx, ny);
2593     }
2594     OUTPUT:
2595     RETVAL
2596    
2597 root 1.1 void
2598 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2599 root 1.1 PROTOTYPE: $$$
2600     PPCODE:
2601     {
2602 root 1.61 maptile *nmap = 0;
2603 root 1.1 I16 nx, ny;
2604    
2605 root 1.291 PUTBACK;
2606 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2607 root 1.291 SPAGAIN;
2608 root 1.1
2609     if (nmap)
2610 root 1.291 for (object *o = nmap->at (nx, ny).bot; o; o = o->above)
2611 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2612 root 1.1 }
2613    
2614     SV *
2615 root 1.309 bot_at (maptile *map, unsigned int x, unsigned int y)
2616 root 1.1 PROTOTYPE: $$$
2617     ALIAS:
2618     top_at = 1
2619     flags_at = 2
2620     light_at = 3
2621     move_block_at = 4
2622     move_slow_at = 5
2623     move_on_at = 6
2624     move_off_at = 7
2625     CODE:
2626 root 1.309 {
2627     sint16 nx = x;
2628     sint16 ny = y;
2629    
2630     if (!xy_normalise (map, nx, ny))
2631     XSRETURN_UNDEF;
2632    
2633     mapspace &ms = map->at (nx, ny);
2634    
2635     ms.update ();
2636    
2637 root 1.1 switch (ix)
2638     {
2639 root 1.309 case 0: RETVAL = to_sv (ms.bot ); break;
2640     case 1: RETVAL = to_sv (ms.top ); break;
2641     case 2: RETVAL = newSVuv (ms.flags_ ); break;
2642     case 3: RETVAL = newSViv (ms.light ); break;
2643     case 4: RETVAL = newSVuv (ms.move_block); break;
2644     case 5: RETVAL = newSVuv (ms.move_slow ); break;
2645     case 6: RETVAL = newSVuv (ms.move_on ); break;
2646     case 7: RETVAL = newSVuv (ms.move_off ); break;
2647 root 1.1 }
2648 root 1.309 }
2649 root 1.122 OUTPUT: RETVAL
2650 root 1.1
2651 root 1.117 # worst xs function of my life
2652 root 1.140 bool
2653 root 1.117 _create_random_map (\
2654 root 1.140 maptile *self,\
2655 root 1.183 utf8_string wallstyle,\
2656     utf8_string wall_name,\
2657     utf8_string floorstyle,\
2658     utf8_string monsterstyle,\
2659     utf8_string treasurestyle,\
2660     utf8_string layoutstyle,\
2661     utf8_string doorstyle,\
2662     utf8_string decorstyle,\
2663     utf8_string origin_map,\
2664     utf8_string final_map,\
2665     utf8_string exitstyle,\
2666     utf8_string this_map,\
2667     utf8_string exit_on_final_map,\
2668 root 1.146 int xsize,\
2669     int ysize,\
2670 root 1.117 int expand2x,\
2671     int layoutoptions1,\
2672     int layoutoptions2,\
2673     int layoutoptions3,\
2674     int symmetry,\
2675     int difficulty,\
2676     int difficulty_given,\
2677     float difficulty_increase,\
2678     int dungeon_level,\
2679     int dungeon_depth,\
2680     int decoroptions,\
2681     int orientation,\
2682     int origin_y,\
2683     int origin_x,\
2684 root 1.146 U32 random_seed,\
2685 root 1.117 val64 total_map_hp,\
2686     int map_layout_style,\
2687     int treasureoptions,\
2688     int symmetry_used,\
2689 root 1.137 region *region,\
2690 root 1.183 utf8_string custom\
2691 root 1.117 )
2692     CODE:
2693     {
2694     random_map_params rmp;
2695    
2696     assign (rmp.wallstyle , wallstyle);
2697     assign (rmp.wall_name , wall_name);
2698     assign (rmp.floorstyle , floorstyle);
2699     assign (rmp.monsterstyle , monsterstyle);
2700     assign (rmp.treasurestyle , treasurestyle);
2701     assign (rmp.layoutstyle , layoutstyle);
2702     assign (rmp.doorstyle , doorstyle);
2703     assign (rmp.decorstyle , decorstyle);
2704     assign (rmp.exitstyle , exitstyle);
2705     assign (rmp.exit_on_final_map, exit_on_final_map);
2706    
2707 root 1.122 rmp.origin_map = origin_map;
2708     rmp.final_map = final_map;
2709     rmp.this_map = this_map;
2710 root 1.146 rmp.xsize = xsize;
2711     rmp.ysize = ysize;
2712 root 1.117 rmp.expand2x = expand2x;
2713     rmp.layoutoptions1 = layoutoptions1;
2714     rmp.layoutoptions2 = layoutoptions2;
2715     rmp.layoutoptions3 = layoutoptions3;
2716     rmp.symmetry = symmetry;
2717     rmp.difficulty = difficulty;
2718     rmp.difficulty_given = difficulty_given;
2719     rmp.difficulty_increase = difficulty_increase;
2720     rmp.dungeon_level = dungeon_level;
2721     rmp.dungeon_depth = dungeon_depth;
2722     rmp.decoroptions = decoroptions;
2723     rmp.orientation = orientation;
2724     rmp.origin_y = origin_y;
2725     rmp.origin_x = origin_x;
2726     rmp.random_seed = random_seed;
2727 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2728 root 1.117 rmp.map_layout_style = map_layout_style;
2729     rmp.treasureoptions = treasureoptions;
2730     rmp.symmetry_used = symmetry_used;
2731     rmp.region = region;
2732 root 1.137 rmp.custom = custom;
2733 root 1.117
2734 root 1.140 RETVAL = self->generate_random_map (&rmp);
2735 root 1.117 }
2736     OUTPUT:
2737     RETVAL
2738    
2739 root 1.293 MODULE = cf PACKAGE = cf::mapspace
2740    
2741     INCLUDE: $PERL $srcdir/genacc mapspace ../include/map.h |
2742    
2743 root 1.19 MODULE = cf PACKAGE = cf::arch
2744 root 1.1
2745 root 1.218 int archetypes_size ()
2746     CODE:
2747     RETVAL = archetypes.size ();
2748     OUTPUT: RETVAL
2749    
2750     archetype *archetypes (U32 index)
2751     CODE:
2752     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2753     OUTPUT: RETVAL
2754 root 1.1
2755 root 1.212 object *instantiate (archetype *arch)
2756     CODE:
2757     RETVAL = arch_to_object (arch);
2758     OUTPUT:
2759     RETVAL
2760    
2761 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2762 root 1.1
2763 root 1.19 MODULE = cf PACKAGE = cf::party
2764 root 1.1
2765 root 1.19 partylist *first ()
2766 root 1.1 PROTOTYPE:
2767 root 1.19 CODE:
2768     RETVAL = get_firstparty ();
2769     OUTPUT: RETVAL
2770 root 1.1
2771 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2772 root 1.1
2773 root 1.19 MODULE = cf PACKAGE = cf::region
2774 root 1.1
2775 root 1.161 void
2776     list ()
2777     PPCODE:
2778     for_all_regions (rgn)
2779     XPUSHs (sv_2mortal (to_sv (rgn)));
2780    
2781 root 1.183 region *find (utf8_string name)
2782 root 1.161 PROTOTYPE: $
2783 root 1.19 CODE:
2784 root 1.161 RETVAL = region::find (name);
2785 root 1.19 OUTPUT: RETVAL
2786 root 1.1
2787 root 1.186 int specificity (region *rgn)
2788     CODE:
2789     RETVAL = 0;
2790     while (rgn = rgn->parent)
2791     RETVAL++;
2792     OUTPUT: RETVAL
2793    
2794 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2795 root 1.1
2796 root 1.19 MODULE = cf PACKAGE = cf::living
2797 root 1.1
2798 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2799 root 1.1
2800 root 1.76 MODULE = cf PACKAGE = cf::settings
2801    
2802 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2803 root 1.76
2804 root 1.84 MODULE = cf PACKAGE = cf::client
2805 root 1.79
2806 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2807 root 1.79
2808 root 1.84 int invoke (client *ns, int event, ...)
2809 root 1.79 CODE:
2810 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2811 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2812     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2813 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2814 root 1.79 OUTPUT: RETVAL
2815    
2816 root 1.84 SV *registry (client *ns)
2817 root 1.79
2818 root 1.100 void
2819     list ()
2820     PPCODE:
2821     EXTEND (SP, clients.size ());
2822     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2823     PUSHs (sv_2mortal (to_sv (*i)));
2824    
2825 root 1.88 void
2826 root 1.100 client::send_packet (SV *packet)
2827     CODE:
2828     {
2829     STRLEN len;
2830     char *buf = SvPVbyte (packet, len);
2831    
2832 root 1.258 if (len > MAXSOCKBUF)
2833     {
2834     // ugly
2835     if (THIS->pl)
2836     THIS->pl->failmsg ("[packet too long for client]");
2837     }
2838     else
2839     THIS->send_packet (buf, len);
2840 root 1.100 }
2841    
2842 root 1.237 faceidx
2843 root 1.238 client::need_face (utf8_string name, int pri = 0)
2844 root 1.237 CODE:
2845 root 1.238 RETVAL = face_find (name, 0);
2846     if (RETVAL)
2847     {
2848     THIS->send_face (RETVAL, pri);
2849     THIS->flush_fx ();
2850     }
2851     OUTPUT:
2852     RETVAL
2853    
2854     int
2855     client::fx_want (int idx, int value = -1)
2856     CODE:
2857     if (0 < idx && idx < FT_NUM)
2858     {
2859     RETVAL = THIS->fx_want [idx];
2860     if (items > 2)
2861     THIS->fx_want [idx] = value;
2862     }
2863     else
2864     RETVAL = 0;
2865 root 1.237 OUTPUT:
2866     RETVAL
2867    
2868 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2869    
2870     faceidx sound_find (utf8_string name)
2871    
2872 root 1.240 void sound_set (utf8_string str, faceidx face)
2873    
2874     # dire hack
2875     void old_sound_index (int idx, faceidx face)
2876     CODE:
2877     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2878     old_sound_index [idx] = face;
2879    
2880 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2881    
2882 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2883 root 1.176
2884 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2885 root 1.176
2886 root 1.183 faceidx alloc (utf8_string name)
2887 root 1.176 CODE:
2888     {
2889     do
2890     {
2891     RETVAL = faces.size ();
2892 root 1.177 faces.resize (RETVAL + 1);
2893 root 1.176 }
2894     while (!RETVAL); // crude way to leave index 0
2895    
2896     faces [RETVAL].name = name;
2897     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2898    
2899     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2900     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2901     }
2902     OUTPUT: RETVAL
2903    
2904 root 1.227 void set_type (faceidx idx, int value)
2905     ALIAS:
2906     set_type = 0
2907     set_visibility = 1
2908     set_magicmap = 2
2909     set_smooth = 3
2910     set_smoothlevel = 4
2911 root 1.176 CODE:
2912 root 1.229 faceinfo *f = face_info (idx); assert (f);
2913 root 1.227 switch (ix)
2914     {
2915     case 0: f->type = value; break;
2916     case 1: f->visibility = value; break;
2917     case 2: f->magicmap = value; break;
2918     case 3: f->smooth = value; break;
2919     case 4: f->smoothlevel = value; break;
2920     }
2921 root 1.177
2922     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2923 root 1.176 CODE:
2924 root 1.182 {
2925 root 1.231 faceinfo *f = face_info (idx); assert (f);
2926     facedata *d = &(faceset ? f->data64 : f->data32);
2927 root 1.181 sv_to (data, d->data);
2928     STRLEN clen;
2929     char *cdata = SvPVbyte (chksum, clen);
2930 root 1.182 clen = min (CHKSUM_SIZE, clen);
2931    
2932     if (memcmp (d->chksum, cdata, clen))
2933     {
2934     memcpy (d->chksum, cdata, clen);
2935    
2936     // invalidate existing client face info
2937     for_all_clients (ns)
2938     if (ns->faceset == faceset)
2939     {
2940     ns->faces_sent [idx] = false;
2941     ns->force_newmap = true;
2942     }
2943     }
2944     }
2945 root 1.176
2946 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2947     CODE:
2948 root 1.267 facedata *d = face_data (idx, faceset);
2949     if (!d) XSRETURN_UNDEF;
2950 root 1.229 RETVAL = d->data.size ();
2951     OUTPUT:
2952     RETVAL
2953    
2954     SV *get_chksum (faceidx idx, int faceset = 0)
2955     CODE:
2956 root 1.267 facedata *d = face_data (idx, faceset);
2957     if (!d) XSRETURN_UNDEF;
2958 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2959     OUTPUT:
2960     RETVAL
2961    
2962 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2963     CODE:
2964     facedata *d = face_data (idx, faceset);
2965     if (!d) XSRETURN_UNDEF;
2966     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2967     OUTPUT:
2968     RETVAL
2969    
2970 root 1.177 void invalidate (faceidx idx)
2971     CODE:
2972     for_all_clients (ns)
2973 root 1.182 {
2974     ns->faces_sent [idx] = false;
2975     ns->force_newmap = true;
2976     }
2977 root 1.177
2978     void invalidate_all ()
2979     CODE:
2980     for_all_clients (ns)
2981 root 1.182 {
2982     ns->faces_sent.reset ();
2983     ns->force_newmap = true;
2984     }
2985 root 1.177
2986 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2987    
2988     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2989    
2990     animidx anim_find (utf8_string name)
2991     CODE:
2992     RETVAL = animation::find (name).number;
2993     OUTPUT: RETVAL
2994    
2995     animidx set (utf8_string name, SV *frames, int facings = 1)
2996     CODE:
2997     {
2998     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2999     croak ("frames must be an arrayref");
3000    
3001     AV *av = (AV *)SvRV (frames);
3002    
3003     animation *anim = &animation::find (name);
3004     if (anim->number)
3005     {
3006     anim->resize (av_len (av) + 1);
3007     anim->facings = facings;
3008     }
3009     else
3010     anim = &animation::create (name, av_len (av) + 1, facings);
3011    
3012     for (int i = 0; i < anim->num_animations; ++i)
3013     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
3014     }
3015     OUTPUT: RETVAL
3016    
3017     void invalidate_all ()
3018     CODE:
3019     for_all_clients (ns)
3020     ns->anims_sent.reset ();
3021    
3022 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
3023    
3024     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
3025    
3026     SV *
3027     new (char *klass)
3028     CODE:
3029     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
3030     OUTPUT: RETVAL
3031    
3032     void
3033     DESTROY (SV *sv)
3034     CODE:
3035     object_freezer *self;
3036     sv_to (sv, self);
3037     delete self;
3038    
3039     MODULE = cf PACKAGE = cf::object::thawer
3040    
3041     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
3042    
3043     SV *
3044     new_from_file (char *klass, octet_string path)
3045     CODE:
3046     object_thawer *f = new object_thawer (path);
3047     if (!*f)
3048     {
3049     delete f;
3050     XSRETURN_UNDEF;
3051     }
3052     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
3053     OUTPUT: RETVAL
3054    
3055     void
3056     DESTROY (SV *sv)
3057     CODE:
3058     object_thawer *self;
3059     sv_to (sv, self);
3060     delete self;
3061    
3062 root 1.252 void
3063 root 1.253 extract_tags (object_thawer *self)
3064 root 1.254 PPCODE:
3065 root 1.252 while (self->kw != KW_EOF)
3066     {
3067 root 1.254 PUTBACK;
3068 root 1.272 coroapi::cede_to_tick ();
3069 root 1.254 SPAGAIN;
3070 root 1.253
3071 root 1.252 if (self->kw == KW_tag)
3072 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
3073 root 1.252
3074     self->skip ();
3075     }
3076