ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.331
Committed: Thu Nov 5 14:38:47 2009 UTC (14 years, 7 months ago) by root
Branch: MAIN
Changes since 1.330: +24 -0 lines
Log Message:
implement match_one

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.331 object *
1228     match_one (const char *expr, object *ob, object *self, object *source, object *originator)
1229     {
1230     if (!strncmp (expr, "match ", sizeof ("match ") - 1))
1231     expr += sizeof ("match ") - 1;
1232    
1233     CALL_BEGIN (5);
1234     CALL_ARG (expr);
1235     CALL_ARG (ob);
1236     CALL_ARG (self);
1237     CALL_ARG (source);
1238     CALL_ARG (originator);
1239     CALL_CALL (cv_cf_match_match, G_ARRAY);
1240    
1241     object *one = 0;
1242    
1243     if (count)
1244     sv_to (TOPs, one);
1245    
1246     CALL_END;
1247    
1248     return one;
1249     }
1250    
1251 root 1.116 /////////////////////////////////////////////////////////////////////////////
1252    
1253 root 1.265 struct EVAPI *evapi::GEVAPI;
1254     struct CoroAPI *coroapi::GCoroAPI;
1255 root 1.80
1256 root 1.314 void
1257     coroapi::do_cede_to_tick ()
1258 root 1.189 {
1259 root 1.272 cede_pending = 0;
1260 root 1.189 cede ();
1261     }
1262 root 1.124
1263 root 1.188 void
1264     coroapi::wait_for_tick ()
1265     {
1266     CALL_BEGIN (0);
1267     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1268     CALL_END;
1269     }
1270    
1271     void
1272     coroapi::wait_for_tick_begin ()
1273     {
1274     CALL_BEGIN (0);
1275     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1276     CALL_END;
1277     }
1278    
1279 root 1.85 void
1280 root 1.80 iow::poll (int events)
1281     {
1282 root 1.265 if (events != this->events)
1283 root 1.81 {
1284 root 1.265 int active = ev_is_active ((ev_io *)this);
1285     if (active) stop ();
1286     ev_io_set ((ev_io *)this, fd, events);
1287     if (active) start ();
1288 root 1.81 }
1289 root 1.80 }
1290    
1291 root 1.314 static void
1292 root 1.324 _connect_to_perl_1 ()
1293 root 1.109 {
1294 root 1.272 stash_cf = gv_stashpv ("cf", 1);
1295 root 1.109
1296     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1297     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1298     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1299     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1300 root 1.293 stash_cf_mapspace_wrap = gv_stashpv ("cf::mapspace::wrap" , 1);
1301 root 1.109 stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1302     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1303     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1304     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1305     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1306    
1307 root 1.272 sv_now = get_sv ("cf::NOW" , 1); SvUPGRADE (sv_now , SVt_NV);
1308     sv_runtime = get_sv ("cf::RUNTIME" , 1); SvUPGRADE (sv_runtime , SVt_NV);
1309     sv_tick_start = get_sv ("cf::TICK_START", 1); SvUPGRADE (sv_tick_start, SVt_NV);
1310     sv_next_tick = get_sv ("cf::NEXT_TICK" , 1); SvUPGRADE (sv_next_tick , SVt_NV);
1311 root 1.116
1312 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1313     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1314     cb_object = get_av ("cf::CB_OBJECT", 1);
1315     cb_player = get_av ("cf::CB_PLAYER", 1);
1316     cb_client = get_av ("cf::CB_CLIENT", 1);
1317     cb_type = get_av ("cf::CB_TYPE" , 1);
1318     cb_map = get_av ("cf::CB_MAP" , 1);
1319 root 1.324 }
1320 root 1.321
1321 root 1.324 static void
1322     _connect_to_perl_2 ()
1323     {
1324     cv_cf_do_invoke = (SV *)get_cv ("cf::do_invoke" , 0); assert (cv_cf_do_invoke);
1325     cv_cf__can_merge = (SV *)get_cv ("cf::_can_merge" , 0); assert (cv_cf__can_merge);
1326     cv_cf_client_send_msg = (SV *)get_cv ("cf::client::send_msg", 0); assert (cv_cf_client_send_msg);
1327     cv_cf_tick = (SV *)get_cv ("cf::tick" , 0); assert (cv_cf_tick);
1328     cv_cf_match_match = (SV *)get_cv ("cf::match::match" , 0); assert (cv_cf_match_match);
1329 root 1.109 }
1330    
1331 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1332    
1333     BOOT:
1334     {
1335 root 1.265 I_EV_API (PACKAGE); evapi::GEVAPI = GEVAPI;
1336     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1337 root 1.80
1338 root 1.324 _connect_to_perl_1 ();
1339 root 1.189
1340 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1341 root 1.63
1342 root 1.220 //{
1343     // require_pv ("Time::HiRes");
1344     //
1345     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1346     // if (!svp) croak ("Time::HiRes is required");
1347     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1348     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1349     //}
1350 root 1.189
1351 root 1.1 static const struct {
1352     const char *name;
1353     IV iv;
1354     } *civ, const_iv[] = {
1355     # define const_iv(name) { # name, (IV)name },
1356 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1357 root 1.198 const_iv (logBacktrace)
1358 root 1.180
1359 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1360    
1361     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1362 root 1.180
1363 root 1.5 const_iv (MAX_TIME)
1364 root 1.258 const_iv (MAXSOCKBUF)
1365 root 1.189
1366 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1367     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1368     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1369     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1370     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1371     const_iv (body_wrist) const_iv (body_waist)
1372 root 1.205
1373 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1374     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1375     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1376     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1377     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1378     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1379     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1380     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1381     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1382     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1383     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1384     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1385     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1386     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1387     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1388     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1389     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1390     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1391     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1392 root 1.326 const_iv (T_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1393 root 1.189 const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1394     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1395     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1396     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1397     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1398     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1399     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1400     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1401 root 1.315 const_iv (MAPSCRIPT) const_iv (SAFE_GROUND)
1402 root 1.1
1403 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1404 root 1.14
1405 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1406     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1407 root 1.1
1408 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1409     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1410     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1411     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1412     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1413     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1414     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1415    
1416     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1417     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1418 root 1.1 const_iv (WEAP_BLUD)
1419    
1420 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1421 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1422 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1423     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1424     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1425     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1426     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1427     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1428     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1429     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1430     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1431     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1432     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1433     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1434     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1435     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1436     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1437     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1438     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1439     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1440     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1441 root 1.298 const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_DEBUG) const_iv (FLAG_BERSERK)
1442 root 1.189 const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1443 root 1.312 const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER) const_iv (FLAG_WIZLOOK)
1444 root 1.189 const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1445     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1446    
1447     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1448     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1449     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1450     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1451 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1452 root 1.299 const_iv (NDI_NOCREATE) const_iv (NDI_CLEAR) const_iv (NDI_VERBATIM)
1453 root 1.1
1454 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1455     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1456    
1457     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1458    
1459 root 1.212 const_iv (SP_RAISE_DEAD)
1460     const_iv (SP_RUNE)
1461     const_iv (SP_MAKE_MARK)
1462     const_iv (SP_BOLT)
1463     const_iv (SP_BULLET)
1464     const_iv (SP_EXPLOSION)
1465     const_iv (SP_CONE)
1466     const_iv (SP_BOMB)
1467     const_iv (SP_WONDER)
1468     const_iv (SP_SMITE)
1469     const_iv (SP_MAGIC_MISSILE)
1470     const_iv (SP_SUMMON_GOLEM)
1471     const_iv (SP_DIMENSION_DOOR)
1472     const_iv (SP_MAGIC_MAPPING)
1473     const_iv (SP_MAGIC_WALL)
1474     const_iv (SP_DESTRUCTION)
1475     const_iv (SP_PERCEIVE_SELF)
1476     const_iv (SP_WORD_OF_RECALL)
1477     const_iv (SP_INVISIBLE)
1478     const_iv (SP_PROBE)
1479     const_iv (SP_HEALING)
1480     const_iv (SP_CREATE_FOOD)
1481     const_iv (SP_EARTH_TO_DUST)
1482     const_iv (SP_CHANGE_ABILITY)
1483     const_iv (SP_BLESS)
1484     const_iv (SP_CURSE)
1485     const_iv (SP_SUMMON_MONSTER)
1486     const_iv (SP_CHARGING)
1487     const_iv (SP_POLYMORPH)
1488     const_iv (SP_ALCHEMY)
1489     const_iv (SP_REMOVE_CURSE)
1490     const_iv (SP_IDENTIFY)
1491     const_iv (SP_DETECTION)
1492     const_iv (SP_MOOD_CHANGE)
1493     const_iv (SP_MOVING_BALL)
1494     const_iv (SP_SWARM)
1495     const_iv (SP_CHANGE_MANA)
1496     const_iv (SP_DISPEL_RUNE)
1497     const_iv (SP_CREATE_MISSILE)
1498     const_iv (SP_CONSECRATE)
1499     const_iv (SP_ANIMATE_WEAPON)
1500     const_iv (SP_LIGHT)
1501     const_iv (SP_CHANGE_MAP_LIGHT)
1502     const_iv (SP_FAERY_FIRE)
1503     const_iv (SP_CAUSE_DISEASE)
1504     const_iv (SP_AURA)
1505     const_iv (SP_TOWN_PORTAL)
1506     const_iv (SP_PARTY_SPELL)
1507    
1508 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1509     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1510 root 1.1 const_iv (F_LOCKED)
1511    
1512 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1513    
1514 root 1.293 const_iv (P_BLOCKSVIEW) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1515 root 1.189 const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1516    
1517     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1518    
1519     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1520 root 1.258 const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR)
1521 root 1.189
1522     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1523     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1524    
1525     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1526    
1527     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1528     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1529     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1530     const_iv (M_ICE) const_iv (M_SPECIAL)
1531    
1532     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1533     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1534    
1535     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1536     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1537     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1538     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1539     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1540     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1541     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1542     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1543     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1544     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1545 root 1.1 const_iv (SK_POISON_NAIL)
1546    
1547 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1548     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1549     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1550     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1551     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1552     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1553    
1554     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1555    
1556     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1557     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1558     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1559     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1560     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1561     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1562     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1563    
1564 root 1.276 const_iv (MAP_ACTIVE) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1565     const_iv (MAP_INACTIVE)
1566 root 1.189
1567     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1568     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1569    
1570 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1571    
1572 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1573    
1574     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1575 root 1.99
1576 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1577 root 1.117
1578     // random map generator
1579 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1580     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1581    
1582     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1583     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1584     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1585    
1586     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1587     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1588 root 1.195
1589     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1590 root 1.281 const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_MINIMAL)
1591 root 1.238
1592     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1593     const_iv (FT_RSRC) const_iv (FT_NUM)
1594 root 1.1 };
1595    
1596     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1597 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1598 root 1.1
1599     static const struct {
1600     const char *name;
1601 root 1.14 int skip;
1602 root 1.7 IV klass;
1603 root 1.1 IV iv;
1604 root 1.6 } *eiv, event_iv[] = {
1605 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1606 root 1.6 # include "eventinc.h"
1607     # undef def
1608     };
1609    
1610     AV *av = get_av ("cf::EVENT", 1);
1611    
1612     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1613 root 1.7 {
1614     AV *event = newAV ();
1615 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1616 root 1.7 av_push (event, newSViv (eiv->klass));
1617     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1618 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1619 root 1.7 }
1620 root 1.324
1621     // used by autogenerated BOOT sections from genacc
1622     av_reflect = get_av ("cf::REFLECT", 1);
1623 root 1.14 }
1624    
1625 root 1.295 void _gv_clear (SV *gv)
1626     CODE:
1627     assert (SvTYPE (gv) == SVt_PVGV);
1628     # define f(sv) { SV *sv_ = (SV *)(sv); sv = 0; SvREFCNT_dec (sv_); }
1629     f (GvGP (gv)->gp_form);
1630     f (GvGP (gv)->gp_io);
1631     f (GvGP (gv)->gp_sv);
1632     f (GvGP (gv)->gp_av);
1633     f (GvGP (gv)->gp_hv);
1634     f (GvGP (gv)->gp_cv);
1635     GvCVGEN (gv) = 0;
1636     GvMULTI_off (gv);
1637     # undef f
1638    
1639 root 1.324 void _connect_to_perl_1 ()
1640    
1641     void _connect_to_perl_2 ()
1642 root 1.14
1643 root 1.210 void _recalc_want ()
1644    
1645 root 1.304 # not used by default anymore
1646 root 1.47 void _global_reattach ()
1647 root 1.14 CODE:
1648     {
1649     // reattach to all attachable objects in the game.
1650 root 1.128 for_all_clients (ns)
1651     ns->reattach ();
1652 root 1.96
1653 root 1.128 for_all_objects (op)
1654 root 1.109 op->reattach ();
1655 root 1.1 }
1656    
1657 root 1.192 # support function for map-world.ext
1658     void _quantise (SV *data_sv, SV *plt_sv)
1659     CODE:
1660     {
1661     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1662     croak ("_quantise called with invalid agruments");
1663    
1664     plt_sv = SvRV (plt_sv);
1665     SV **plt = AvARRAY (plt_sv);
1666     int plt_count = AvFILL (plt_sv) + 1;
1667    
1668     STRLEN len;
1669     char *data = SvPVbyte (data_sv, len);
1670     char *dst = data;
1671    
1672     while (len >= 3)
1673     {
1674     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1675     {
1676     char *val = SvPVX (*val_sv);
1677    
1678     if (val [0] == data [0]
1679     && val [1] == data [1]
1680     && val [2] == data [2])
1681     {
1682     *dst++ = val [3];
1683     goto next;
1684     }
1685     }
1686    
1687     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1688     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1689     dst - SvPVX (data_sv), len);
1690    
1691     next:
1692     data += 3;
1693     len -= 3;
1694     }
1695    
1696     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1697     }
1698    
1699 root 1.303 void init_anim ()
1700    
1701     void init_globals ()
1702    
1703     void init_experience ()
1704    
1705     void init_attackmess ()
1706    
1707     void init_dynamic ()
1708    
1709     void load_settings ()
1710    
1711     void load_materials ()
1712    
1713     void init_uuid ()
1714     CODE:
1715     UUID::init ();
1716    
1717     void init_signals ()
1718    
1719     void init_commands ()
1720    
1721     void init_skills ()
1722    
1723     void init_beforeplay ()
1724    
1725 root 1.273 void evthread_start (int aiofd)
1726 root 1.272
1727     void cede_to_tick ()
1728 root 1.236 CODE:
1729 root 1.272 coroapi::cede_to_tick ();
1730 root 1.236
1731 root 1.272 NV till_tick ()
1732 root 1.236 CODE:
1733 root 1.272 RETVAL = SvNVX (sv_next_tick) - now ();
1734 root 1.236 OUTPUT:
1735     RETVAL
1736    
1737 root 1.272 int tick_inhibit ()
1738 root 1.236 CODE:
1739 root 1.272 RETVAL = tick_inhibit;
1740 root 1.236 OUTPUT:
1741     RETVAL
1742    
1743 root 1.272 void tick_inhibit_inc ()
1744     CODE:
1745     ++tick_inhibit;
1746    
1747     void tick_inhibit_dec ()
1748     CODE:
1749     if (!--tick_inhibit)
1750     if (tick_pending)
1751     {
1752     ev_async_send (EV_DEFAULT, &tick_watcher);
1753     coroapi::cede ();
1754     }
1755    
1756     void server_tick ()
1757     CODE:
1758     {
1759     NOW = ev_now (EV_DEFAULT);
1760     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1761     SvNV_set (sv_tick_start, NOW); SvNOK_only (sv_tick_start);
1762     runtime = SvNVX (sv_runtime);
1763    
1764     server_tick ();
1765    
1766     NOW = ev_time ();
1767     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1768     runtime += TICK;
1769     SvNV_set (sv_runtime, runtime); SvNOK_only (sv_runtime);
1770     }
1771    
1772 root 1.1 NV floor (NV x)
1773    
1774     NV ceil (NV x)
1775    
1776 root 1.143 NV rndm (...)
1777 root 1.286 ALIAS:
1778     rmg_rndm = 1
1779 root 1.143 CODE:
1780 root 1.286 {
1781     rand_gen &gen = ix ? rmg_rndm : rndm;
1782 root 1.143 switch (items)
1783     {
1784 root 1.286 case 0: RETVAL = gen (); break;
1785     case 1: RETVAL = gen (SvUV (ST (0))); break;
1786     case 2: RETVAL = gen (SvIV (ST (0)), SvIV (ST (1))); break;
1787 root 1.143 default: croak ("cf::rndm requires none, one or two parameters."); break;
1788     }
1789 root 1.286 }
1790 root 1.143 OUTPUT:
1791     RETVAL
1792    
1793 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1794     CODE:
1795     RETVAL = clamp (value, min_value, max_value);
1796     OUTPUT:
1797     RETVAL
1798    
1799     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1800     CODE:
1801     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1802     OUTPUT:
1803     RETVAL
1804    
1805 root 1.268 void weaken (...)
1806     PROTOTYPE: @
1807     CODE:
1808     while (items > 0)
1809     sv_rvweaken (ST (--items));
1810    
1811 root 1.1 void
1812 root 1.198 log_backtrace (utf8_string msg)
1813    
1814     void
1815     LOG (int flags, utf8_string msg)
1816 root 1.1 PROTOTYPE: $$
1817 root 1.198 C_ARGS: flags, "%s", msg
1818 root 1.1
1819 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1820 root 1.1 PROTOTYPE: $$
1821    
1822 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1823 root 1.1 PROTOTYPE: $$
1824    
1825     void
1826     sub_generation_inc ()
1827     CODE:
1828     PL_sub_generation++;
1829    
1830 root 1.183 const_octet_string
1831 root 1.1 mapdir ()
1832     PROTOTYPE:
1833     ALIAS:
1834     mapdir = 0
1835     uniquedir = 1
1836     tmpdir = 2
1837     confdir = 3
1838     localdir = 4
1839     playerdir = 5
1840     datadir = 6
1841     CODE:
1842 root 1.19 switch (ix)
1843     {
1844     case 0: RETVAL = settings.mapdir ; break;
1845     case 1: RETVAL = settings.uniquedir; break;
1846     case 2: RETVAL = settings.tmpdir ; break;
1847     case 3: RETVAL = settings.confdir ; break;
1848     case 4: RETVAL = settings.localdir ; break;
1849     case 5: RETVAL = settings.playerdir; break;
1850     case 6: RETVAL = settings.datadir ; break;
1851     }
1852 root 1.1 OUTPUT: RETVAL
1853    
1854 root 1.120 void abort ()
1855    
1856 root 1.199 void reset_signals ()
1857    
1858 root 1.270 void fork_abort (const_octet_string cause = "cf::fork_abort")
1859 root 1.144
1860 root 1.270 void cleanup (const_octet_string cause, bool make_core = false)
1861 root 1.134
1862 root 1.116 void emergency_save ()
1863    
1864 root 1.156 void _exit (int status = EXIT_SUCCESS)
1865    
1866 root 1.125 #if _POSIX_MEMLOCK
1867    
1868     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1869 root 1.271 INIT:
1870 root 1.279 #if __GLIBC__
1871 root 1.300 mallopt (M_TOP_PAD, 1024 * 1024);
1872     mallopt (M_MMAP_THRESHOLD, 1024 * 1024 * 128);
1873     mallopt (M_MMAP_MAX, 0); // likely bug-workaround, also frees memory
1874 root 1.279 mallopt (M_PERTURB, 0xee); // bug-workaround for linux glibc+mlockall+calloc
1875 root 1.277 #endif
1876 root 1.125
1877     int munlockall ()
1878    
1879     #endif
1880    
1881 root 1.279 int
1882     malloc_trim (IV pad = 0)
1883    
1884     void
1885     mallinfo ()
1886     PPCODE:
1887     {
1888     #if __GLIBC__
1889     struct mallinfo mai = mallinfo ();
1890     EXTEND (SP, 10*2);
1891     PUSHs (sv_2mortal (newSVpv ("arena" , 0))); PUSHs (sv_2mortal (newSViv (mai.arena)));
1892     PUSHs (sv_2mortal (newSVpv ("ordblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.ordblks)));
1893     PUSHs (sv_2mortal (newSVpv ("smblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.smblks)));
1894     PUSHs (sv_2mortal (newSVpv ("hblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblks)));
1895     PUSHs (sv_2mortal (newSVpv ("hblkhd" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblkhd)));
1896     PUSHs (sv_2mortal (newSVpv ("usmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.usmblks)));
1897     PUSHs (sv_2mortal (newSVpv ("fsmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.fsmblks)));
1898     PUSHs (sv_2mortal (newSVpv ("uordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.uordblks)));
1899     PUSHs (sv_2mortal (newSVpv ("fordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.fordblks)));
1900     PUSHs (sv_2mortal (newSVpv ("keepcost", 0))); PUSHs (sv_2mortal (newSViv (mai.keepcost)));
1901     #endif
1902 root 1.308 EXTEND (SP, 5*2);
1903 root 1.279 PUSHs (sv_2mortal (newSVpv ("slice_alloc", 0))); PUSHs (sv_2mortal (newSVuv (slice_alloc)));
1904     PUSHs (sv_2mortal (newSVpv ("shstr_alloc", 0))); PUSHs (sv_2mortal (newSVuv (shstr_alloc)));
1905 root 1.282 PUSHs (sv_2mortal (newSVpv ("objects" , 0))); PUSHs (sv_2mortal (newSVuv (objects.size () * sizeof (object))));
1906 root 1.308 PUSHs (sv_2mortal (newSVpv ("sv_count" , 0))); PUSHs (sv_2mortal (newSVuv (PL_sv_count)));
1907     PUSHs (sv_2mortal (newSVpv ("sv_objcount", 0))); PUSHs (sv_2mortal (newSVuv (PL_sv_objcount)));
1908 root 1.279 }
1909    
1910 root 1.183 int find_animation (utf8_string text)
1911 root 1.1 PROTOTYPE: $
1912    
1913 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1914 root 1.1
1915 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1916 root 1.1
1917     int
1918     exp_to_level (val64 exp)
1919     CODE:
1920     {
1921     int i = 0;
1922    
1923     RETVAL = settings.max_level;
1924    
1925     for (i = 1; i <= settings.max_level; i++)
1926     {
1927     if (levels[i] > exp)
1928     {
1929     RETVAL = i - 1;
1930     break;
1931     }
1932     }
1933     }
1934     OUTPUT: RETVAL
1935    
1936     val64
1937     level_to_min_exp (int level)
1938     CODE:
1939     if (level > settings.max_level)
1940     RETVAL = levels[settings.max_level];
1941     else if (level < 1)
1942     RETVAL = 0;
1943     else
1944     RETVAL = levels[level];
1945     OUTPUT: RETVAL
1946    
1947     SV *
1948     resistance_to_string (int atnr)
1949     CODE:
1950     if (atnr >= 0 && atnr < NROFATTACKS)
1951     RETVAL = newSVpv (resist_plus[atnr], 0);
1952     else
1953     XSRETURN_UNDEF;
1954     OUTPUT: RETVAL
1955    
1956 root 1.275 UUID
1957 root 1.274 uuid_cur ()
1958     CODE:
1959 root 1.275 RETVAL = UUID::cur;
1960 root 1.274 OUTPUT:
1961     RETVAL
1962    
1963 root 1.275 UUID
1964 root 1.274 uuid_gen ()
1965     CODE:
1966 root 1.275 RETVAL = UUID::gen ();
1967     OUTPUT:
1968     RETVAL
1969    
1970     val64
1971     uuid_seq (UUID uuid)
1972     CODE:
1973     RETVAL = uuid.seq;
1974     OUTPUT:
1975     RETVAL
1976    
1977     UUID
1978     uuid_str (val64 seq)
1979     CODE:
1980     RETVAL.seq = seq;
1981 root 1.274 OUTPUT:
1982     RETVAL
1983    
1984     void
1985     coin_names ()
1986     PPCODE:
1987     EXTEND (SP, NUM_COINS);
1988     for (int i = 0; i < NUM_COINS; ++i)
1989     PUSHs (sv_2mortal (newSVpv (coins [i], 0)));
1990    
1991     void
1992     coin_archetypes ()
1993     PPCODE:
1994     EXTEND (SP, NUM_COINS);
1995     for (int i = 0; i < NUM_COINS; ++i)
1996     PUSHs (sv_2mortal (to_sv (archetype::find (coins [i]))));
1997    
1998 root 1.162 bool
1999 root 1.278 load_resource_file_ (octet_string filename)
2000 root 1.162
2001 root 1.288 void
2002     fix_weight ()
2003    
2004 root 1.97 MODULE = cf PACKAGE = cf::attachable
2005    
2006 root 1.27 int
2007 root 1.97 valid (SV *obj)
2008 root 1.27 CODE:
2009     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
2010     OUTPUT:
2011     RETVAL
2012    
2013 root 1.164 void
2014     debug_trace (attachable *obj, bool on = true)
2015     CODE:
2016     obj->flags &= ~attachable::F_DEBUG_TRACE;
2017     if (on)
2018     obj->flags |= attachable::F_DEBUG_TRACE;
2019    
2020 root 1.153 int mortals_size ()
2021     CODE:
2022     RETVAL = attachable::mortals.size ();
2023     OUTPUT: RETVAL
2024    
2025     #object *mortals (U32 index)
2026     # CODE:
2027     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
2028     # OUTPUT: RETVAL
2029    
2030 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
2031 root 1.115
2032 root 1.101 MODULE = cf PACKAGE = cf::global
2033    
2034     int invoke (SV *klass, int event, ...)
2035     CODE:
2036     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
2037     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2038     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2039 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
2040 root 1.101 OUTPUT: RETVAL
2041    
2042 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
2043    
2044 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
2045 root 1.62
2046 root 1.18 int invoke (object *op, int event, ...)
2047     CODE:
2048     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
2049 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2050     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2051 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
2052 root 1.18 OUTPUT: RETVAL
2053    
2054     SV *registry (object *op)
2055    
2056 root 1.134 int objects_size ()
2057     CODE:
2058     RETVAL = objects.size ();
2059     OUTPUT: RETVAL
2060    
2061     object *objects (U32 index)
2062     CODE:
2063     RETVAL = index < objects.size () ? objects [index] : 0;
2064     OUTPUT: RETVAL
2065    
2066     int actives_size ()
2067     CODE:
2068     RETVAL = actives.size ();
2069     OUTPUT: RETVAL
2070    
2071     object *actives (U32 index)
2072 root 1.57 CODE:
2073 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
2074 root 1.57 OUTPUT: RETVAL
2075    
2076 root 1.283 int mortals_size ()
2077     CODE:
2078     RETVAL = attachable::mortals.size ();
2079     OUTPUT: RETVAL
2080    
2081 root 1.215 const char *slot_use_name (U32 slot)
2082 root 1.205 ALIAS:
2083 root 1.215 slot_nonuse_name = 1
2084 root 1.205 CODE:
2085     {
2086     if (slot >= NUM_BODY_LOCATIONS)
2087     croak ("body slot index out of range");
2088    
2089     switch (ix)
2090     {
2091 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
2092     case 1: RETVAL = body_locations[slot].nonuse_name; break;
2093 root 1.205 }
2094     }
2095     OUTPUT:
2096     RETVAL
2097    
2098 root 1.1 # missing properties
2099    
2100 root 1.54 object *head (object *op)
2101     PROTOTYPE: $
2102     CODE:
2103 root 1.134 RETVAL = op->head_ ();
2104 root 1.54 OUTPUT: RETVAL
2105    
2106 root 1.1 void
2107     inv (object *obj)
2108     PROTOTYPE: $
2109     PPCODE:
2110     {
2111 root 1.254 for (object *o = obj->inv; o; o = o->below)
2112 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
2113 root 1.1 }
2114    
2115 root 1.102 void
2116     set_animation (object *op, int idx)
2117     CODE:
2118     SET_ANIMATION (op, idx);
2119    
2120 elmex 1.160 int
2121     num_animations (object *op)
2122     CODE:
2123     RETVAL = NUM_ANIMATIONS (op);
2124     OUTPUT: RETVAL
2125    
2126 root 1.205 int slot_info (object *op, UV slot, int value = 0)
2127     ALIAS:
2128     slot_used = 1
2129     CODE:
2130     {
2131     if (slot >= NUM_BODY_LOCATIONS)
2132     croak ("body slot index out of range");
2133    
2134 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
2135 root 1.205
2136     if (items > 2)
2137     if (ix)
2138 root 1.208 op->slot[slot].used = value;
2139     else
2140 root 1.205 op->slot[slot].info = value;
2141     }
2142     OUTPUT:
2143     RETVAL
2144    
2145 root 1.183 object *find_best_object_match (object *op, utf8_string match)
2146 root 1.58
2147     object *find_marked_object (object *op)
2148    
2149 root 1.109 int need_identify (object *obj);
2150 root 1.1
2151     int apply_shop_mat (object *shop_mat, object *op);
2152    
2153 root 1.27 int move (object *op, int dir, object *originator = op)
2154     CODE:
2155     RETVAL = move_ob (op, dir, originator);
2156     OUTPUT:
2157     RETVAL
2158 root 1.1
2159 root 1.74 void apply (object *applier, object *applied, int flags = 0)
2160     CODE:
2161     manual_apply (applied, applier, flags);
2162 root 1.1
2163 root 1.74 void apply_below (object *op)
2164     CODE:
2165     player_apply_below (op);
2166 root 1.1
2167 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
2168    
2169 root 1.330 int casting_level (object *caster, object *spell)
2170    
2171 root 1.74 int pay_item (object *op, object *buyer)
2172     CODE:
2173     RETVAL = pay_for_item (op, buyer);
2174     OUTPUT: RETVAL
2175 root 1.1
2176 root 1.74 int pay_amount (object *op, uint64 amount)
2177     CODE:
2178     RETVAL = pay_for_amount (amount, op);
2179     OUTPUT: RETVAL
2180 root 1.1
2181     void pay_player (object *op, uint64 amount)
2182    
2183 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
2184 root 1.1
2185 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
2186 root 1.1
2187 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
2188     CODE:
2189     do_learn_spell (op, sp, special_prayer);
2190 root 1.1
2191 root 1.74 void forget_spell (object *op, object *sp)
2192     CODE:
2193     do_forget_spell (op, query_name (sp));
2194 root 1.1
2195 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2196 root 1.74 CODE:
2197     RETVAL = check_spell_known (op, spellname);
2198     OUTPUT: RETVAL
2199 root 1.1
2200 root 1.74 int query_money (object *op)
2201 root 1.1 ALIAS: money = 0
2202    
2203 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2204 root 1.1 ALIAS: cost = 0
2205    
2206 root 1.74 void spring_trap (object *op, object *victim)
2207 root 1.1
2208 root 1.74 int check_trigger (object *op, object *cause)
2209 root 1.1
2210 root 1.74 void drop (object *who, object *op)
2211 root 1.1
2212 root 1.74 void pick_up (object *who, object *op)
2213 root 1.1
2214 root 1.102 void update_object (object *op, int action)
2215 root 1.1
2216 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2217 root 1.1
2218     void player_lvl_adj (object *who, object *skill = 0)
2219    
2220     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2221    
2222     int calc_skill_exp (object *who, object *op, object *skill);
2223    
2224 root 1.316 void push_button (object *op, object *originator);
2225 root 1.1
2226 root 1.316 void use_trigger (object *op, object *originator);
2227 root 1.1
2228 elmex 1.232 void handle_apply_yield (object *op);
2229    
2230 elmex 1.319 int convert_item (object *item, object *converter);
2231    
2232 root 1.1
2233     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2234    
2235     # no clean way to get an object from an archetype - stupid idiotic
2236     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2237    
2238 root 1.183 object *new (utf8_string archetype = 0)
2239 root 1.1 PROTOTYPE: ;$
2240     CODE:
2241 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2242 root 1.1 OUTPUT:
2243     RETVAL
2244    
2245 root 1.225 object *find_object (U32 tag)
2246    
2247 root 1.218 # TODO: nuke
2248 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2249 root 1.1 PROTOTYPE: $$$$$$
2250     CODE:
2251     {
2252 root 1.257 RETVAL = insert_ob_in_map_at (ob, where, orig, flag, x, y);
2253 root 1.329
2254     if (RETVAL->destroyed ())
2255     RETVAL = 0;
2256 root 1.1 }
2257    
2258 root 1.284 shstr
2259     object::kv_get (shstr key)
2260 root 1.1
2261 root 1.284 void
2262     object::kv_del (shstr key)
2263    
2264     void
2265     object::kv_set (shstr key, shstr value)
2266 root 1.1
2267     object *get_nearest_player (object *ob)
2268     ALIAS: nearest_player = 0
2269     PREINIT:
2270     extern object *get_nearest_player (object *);
2271    
2272     void rangevector (object *ob, object *other, int flags = 0)
2273     PROTOTYPE: $$;$
2274     PPCODE:
2275     {
2276     rv_vector rv;
2277 root 1.291
2278     PUTBACK;
2279 root 1.1 get_rangevector (ob, other, &rv, flags);
2280 root 1.291 SPAGAIN;
2281    
2282 root 1.1 EXTEND (SP, 5);
2283     PUSHs (newSVuv (rv.distance));
2284     PUSHs (newSViv (rv.distance_x));
2285     PUSHs (newSViv (rv.distance_y));
2286     PUSHs (newSViv (rv.direction));
2287 root 1.257 PUSHs (to_sv (rv.part));
2288 root 1.1 }
2289    
2290     bool on_same_map_as (object *ob, object *other)
2291     CODE:
2292     RETVAL = on_same_map (ob, other);
2293     OUTPUT: RETVAL
2294    
2295 root 1.183 const_utf8_string
2296 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2297 root 1.1 CODE:
2298 root 1.58 RETVAL = query_base_name (op, plural);
2299 root 1.1 OUTPUT: RETVAL
2300    
2301 root 1.256 # return the tail of an object, excluding itself
2302     void
2303     tail (object *op)
2304     PPCODE:
2305     while ((op = op->more))
2306     XPUSHs (sv_2mortal (to_sv (op)));
2307    
2308 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2309    
2310     player *player (object *op)
2311     CODE:
2312     RETVAL = op->contr;
2313     OUTPUT: RETVAL
2314    
2315 root 1.257 bool move_player (object *op, int dir)
2316    
2317 root 1.105 void check_score (object *op)
2318    
2319 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2320 root 1.120 CODE:
2321     new_draw_info (flags, 0, op, txt);
2322 root 1.1
2323     void kill_player (object *op)
2324    
2325 root 1.257 void esrv_send_item (object *pl, object *item)
2326    
2327     void esrv_update_item (object *pl, int what, object *item)
2328     C_ARGS: what, pl, item
2329    
2330     void esrv_del_item (object *pl, int tag)
2331     C_ARGS: pl->contr, tag
2332 root 1.58
2333 root 1.183 int command_summon (object *op, utf8_string params)
2334 root 1.67
2335 root 1.183 int command_arrest (object *op, utf8_string params)
2336 root 1.67
2337 root 1.66
2338 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2339 root 1.1
2340 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2341 root 1.62
2342 root 1.18 int invoke (player *pl, int event, ...)
2343     CODE:
2344     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2345 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2346     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2347 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2348 root 1.18 OUTPUT: RETVAL
2349    
2350 root 1.12 SV *registry (player *pl)
2351 root 1.1
2352 root 1.102 void
2353     save_stats (player *pl)
2354     CODE:
2355     pl->ob->stats.hp = pl->ob->stats.maxhp;
2356     pl->ob->stats.sp = pl->ob->stats.maxsp;
2357     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2358     pl->orig_stats = pl->ob->stats;
2359    
2360 root 1.307 # should only be temporary
2361 elmex 1.306 void esrv_new_player (player *pl)
2362    
2363 root 1.310 #d# TODO: replace by blocked_los accessor, fix code using this
2364 root 1.1 bool
2365     cell_visible (player *pl, int dx, int dy)
2366     CODE:
2367 root 1.310 RETVAL = pl->blocked_los (dx, dy) != LOS_BLOCKED;
2368 root 1.1 OUTPUT:
2369     RETVAL
2370    
2371 root 1.4 void
2372 root 1.1 send (player *pl, SV *packet)
2373     CODE:
2374     {
2375     STRLEN len;
2376     char *buf = SvPVbyte (packet, len);
2377    
2378 root 1.258 if (len > MAXSOCKBUF)
2379     pl->failmsg ("[packet too long for client]");
2380     else if (pl->ns)
2381 root 1.100 pl->ns->send_packet (buf, len);
2382 root 1.1 }
2383    
2384 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2385 root 1.45 PROTOTYPE: $;$$$
2386 root 1.1 PPCODE:
2387 root 1.45 if (GIMME_V != G_VOID)
2388     {
2389     EXTEND (SP, 3);
2390     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2391     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2392     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2393     }
2394 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2395     if (x) sv_to (x, pl->bed_x);
2396     if (y) sv_to (y, pl->bed_y);
2397 root 1.1
2398     void
2399     list ()
2400     PPCODE:
2401 root 1.128 for_all_players (pl)
2402 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2403 root 1.1
2404    
2405     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2406    
2407 root 1.61 int invoke (maptile *map, int event, ...)
2408 root 1.18 CODE:
2409     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2410 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2411     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2412 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2413 root 1.25 OUTPUT: RETVAL
2414 root 1.18
2415 root 1.61 SV *registry (maptile *map)
2416 root 1.12
2417 root 1.255 void
2418     find_tagged_objects (maptile *map, utf8_string tag = 0)
2419     PPCODE:
2420     {
2421     if (!map->spaces)
2422     XSRETURN_EMPTY;
2423    
2424     if (tag)
2425     {
2426     shstr_cmp tag_ (tag);
2427    
2428     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2429     for (object *op = ms->bot; op; op = op->above)
2430     if (op->tag == tag_)
2431     XPUSHs (sv_2mortal (to_sv (op)));
2432     }
2433     else
2434     {
2435     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2436     for (object *op = ms->bot; op; op = op->above)
2437     if (op->tag)
2438     XPUSHs (sv_2mortal (to_sv (op)));
2439     }
2440     }
2441    
2442 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2443 root 1.1
2444 root 1.116 void
2445 root 1.312 adjust_daylight ()
2446     CODE:
2447     maptile::adjust_daylight ();
2448    
2449 root 1.318 int
2450     outdoor_darkness (int darkness = 0)
2451     CODE:
2452     RETVAL = maptile::outdoor_darkness;
2453     if (items)
2454     maptile::outdoor_darkness = darkness;
2455     OUTPUT:
2456     RETVAL
2457    
2458 root 1.312 void
2459 root 1.116 maptile::instantiate ()
2460    
2461     maptile *new ()
2462 root 1.1 PROTOTYPE:
2463     CODE:
2464 root 1.116 RETVAL = new maptile;
2465 root 1.1 OUTPUT:
2466     RETVAL
2467    
2468 root 1.116 void
2469 root 1.117 maptile::players ()
2470     PPCODE:
2471     if (GIMME_V == G_SCALAR)
2472 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2473 root 1.117 else if (GIMME_V == G_ARRAY)
2474     {
2475     EXTEND (SP, THIS->players);
2476     for_all_players (pl)
2477     if (pl->ob && pl->ob->map == THIS)
2478 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2479 root 1.117 }
2480    
2481 root 1.156 void
2482 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2483 root 1.156 CODE:
2484     {
2485 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2486     croak ("maptile::add_underlay: palette must be arrayref");
2487 root 1.156
2488 root 1.168 palette = SvRV (palette);
2489 root 1.156
2490 root 1.168 STRLEN idxlen;
2491     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2492 root 1.156
2493 root 1.168 for (int x = 0; x < THIS->width; ++x)
2494     for (int y = 0; y < THIS->height; ++y)
2495     {
2496     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2497     if (op->flag [FLAG_IS_FLOOR])
2498     goto skip_space;
2499    
2500     {
2501     int offs = offset + y * stride + x;
2502     if (IN_RANGE_EXC (offs, 0, idxlen))
2503     {
2504     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2505     {
2506     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2507     ob->flag [FLAG_NO_MAP_SAVE] = true;
2508     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2509 root 1.200
2510     if (ob->randomitems)
2511     {
2512 root 1.203 if (!ob->above)
2513     {
2514     ob->create_treasure (ob->randomitems);
2515    
2516     for (object *op = ob->above; op; op = op->above)
2517     op->flag [FLAG_NO_MAP_SAVE] = true;
2518     }
2519    
2520 root 1.200 ob->randomitems = 0;
2521     }
2522 root 1.168 }
2523     }
2524     }
2525 root 1.156
2526 root 1.168 skip_space: ;
2527     }
2528     }
2529    
2530     void
2531     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2532     CODE:
2533     {
2534     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2535     croak ("maptile::set_regiondata: palette must be arrayref");
2536    
2537     palette = SvRV (palette);
2538    
2539     STRLEN idxlen;
2540     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2541    
2542 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2543 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2544    
2545     for (int i = av_len ((AV *)palette) + 1; i--; )
2546 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2547 root 1.168
2548     for (int y = 0; y < THIS->height; ++y)
2549     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2550    
2551     sfree (THIS->regions, THIS->size ());
2552 root 1.230 delete [] THIS->regionmap;
2553 root 1.168
2554     THIS->regions = regions;
2555 root 1.156 THIS->regionmap = regionmap;
2556     }
2557    
2558 root 1.193 void
2559     maptile::create_region_treasure ()
2560     CODE:
2561     for (int x = 0; x < THIS->width; ++x)
2562     for (int y = 0; y < THIS->height; ++y)
2563     {
2564     region *rgn = THIS->region (x, y);
2565    
2566     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2567 root 1.301 if (object *op = THIS->at (x, y).top)
2568     if (rgn->treasure && rndm () < rgn->treasure_density)
2569 root 1.193 create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2570     }
2571    
2572 root 1.74 int out_of_map (maptile *map, int x, int y)
2573    
2574 root 1.29 void
2575 root 1.315 find_link (maptile *map, shstr_tmp connection)
2576 root 1.29 PPCODE:
2577 root 1.315 if (oblinkpt *obp = map->find_link (connection))
2578 root 1.29 for (objectlink *ol = obp->link; ol; ol = ol->next)
2579 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2580 root 1.1
2581     void
2582 root 1.140 get_map_flags (maptile *map, int x, int y)
2583 root 1.1 PPCODE:
2584     {
2585 root 1.61 maptile *nmap = 0;
2586 root 1.1 I16 nx = 0, ny = 0;
2587 root 1.291
2588     PUTBACK;
2589 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2590 root 1.291 SPAGAIN;
2591 root 1.1
2592     EXTEND (SP, 4);
2593     PUSHs (sv_2mortal (newSViv (flags)));
2594    
2595     if (GIMME_V == G_ARRAY)
2596     {
2597 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2598 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2599     PUSHs (sv_2mortal (newSViv (ny)));
2600     }
2601     }
2602    
2603 root 1.293 mapspace *
2604     ms (maptile *map, unsigned int x, unsigned int y)
2605     PROTOTYPE: $$$
2606     CODE:
2607     {
2608     maptile *nmap = 0;
2609     I16 nx, ny;
2610    
2611     PUTBACK;
2612     get_map_flags (map, &nmap, x, y, &nx, &ny);
2613     SPAGAIN;
2614    
2615     if (!nmap)
2616     XSRETURN_UNDEF;
2617    
2618     RETVAL = &nmap->at (nx, ny);
2619     }
2620     OUTPUT:
2621     RETVAL
2622    
2623 root 1.1 void
2624 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2625 root 1.1 PROTOTYPE: $$$
2626     PPCODE:
2627     {
2628 root 1.61 maptile *nmap = 0;
2629 root 1.1 I16 nx, ny;
2630    
2631 root 1.291 PUTBACK;
2632 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2633 root 1.291 SPAGAIN;
2634 root 1.1
2635     if (nmap)
2636 root 1.291 for (object *o = nmap->at (nx, ny).bot; o; o = o->above)
2637 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2638 root 1.1 }
2639    
2640     SV *
2641 root 1.309 bot_at (maptile *map, unsigned int x, unsigned int y)
2642 root 1.1 PROTOTYPE: $$$
2643     ALIAS:
2644     top_at = 1
2645     flags_at = 2
2646     light_at = 3
2647     move_block_at = 4
2648     move_slow_at = 5
2649     move_on_at = 6
2650     move_off_at = 7
2651     CODE:
2652 root 1.309 {
2653     sint16 nx = x;
2654     sint16 ny = y;
2655    
2656     if (!xy_normalise (map, nx, ny))
2657     XSRETURN_UNDEF;
2658    
2659     mapspace &ms = map->at (nx, ny);
2660    
2661     ms.update ();
2662    
2663 root 1.1 switch (ix)
2664     {
2665 root 1.309 case 0: RETVAL = to_sv (ms.bot ); break;
2666     case 1: RETVAL = to_sv (ms.top ); break;
2667     case 2: RETVAL = newSVuv (ms.flags_ ); break;
2668     case 3: RETVAL = newSViv (ms.light ); break;
2669     case 4: RETVAL = newSVuv (ms.move_block); break;
2670     case 5: RETVAL = newSVuv (ms.move_slow ); break;
2671     case 6: RETVAL = newSVuv (ms.move_on ); break;
2672     case 7: RETVAL = newSVuv (ms.move_off ); break;
2673 root 1.1 }
2674 root 1.309 }
2675 root 1.122 OUTPUT: RETVAL
2676 root 1.1
2677 root 1.117 # worst xs function of my life
2678 root 1.140 bool
2679 root 1.117 _create_random_map (\
2680 root 1.140 maptile *self,\
2681 root 1.183 utf8_string wallstyle,\
2682     utf8_string wall_name,\
2683     utf8_string floorstyle,\
2684     utf8_string monsterstyle,\
2685     utf8_string treasurestyle,\
2686     utf8_string layoutstyle,\
2687     utf8_string doorstyle,\
2688     utf8_string decorstyle,\
2689     utf8_string origin_map,\
2690     utf8_string final_map,\
2691     utf8_string exitstyle,\
2692     utf8_string this_map,\
2693     utf8_string exit_on_final_map,\
2694 root 1.146 int xsize,\
2695     int ysize,\
2696 root 1.117 int expand2x,\
2697     int layoutoptions1,\
2698     int layoutoptions2,\
2699     int layoutoptions3,\
2700     int symmetry,\
2701     int difficulty,\
2702     int difficulty_given,\
2703     float difficulty_increase,\
2704     int dungeon_level,\
2705     int dungeon_depth,\
2706     int decoroptions,\
2707     int orientation,\
2708     int origin_y,\
2709     int origin_x,\
2710 root 1.146 U32 random_seed,\
2711 root 1.117 val64 total_map_hp,\
2712     int map_layout_style,\
2713     int treasureoptions,\
2714     int symmetry_used,\
2715 root 1.137 region *region,\
2716 root 1.183 utf8_string custom\
2717 root 1.117 )
2718     CODE:
2719     {
2720     random_map_params rmp;
2721    
2722     assign (rmp.wallstyle , wallstyle);
2723     assign (rmp.wall_name , wall_name);
2724     assign (rmp.floorstyle , floorstyle);
2725     assign (rmp.monsterstyle , monsterstyle);
2726     assign (rmp.treasurestyle , treasurestyle);
2727     assign (rmp.layoutstyle , layoutstyle);
2728     assign (rmp.doorstyle , doorstyle);
2729     assign (rmp.decorstyle , decorstyle);
2730     assign (rmp.exitstyle , exitstyle);
2731     assign (rmp.exit_on_final_map, exit_on_final_map);
2732    
2733 root 1.122 rmp.origin_map = origin_map;
2734     rmp.final_map = final_map;
2735     rmp.this_map = this_map;
2736 root 1.146 rmp.xsize = xsize;
2737     rmp.ysize = ysize;
2738 root 1.117 rmp.expand2x = expand2x;
2739     rmp.layoutoptions1 = layoutoptions1;
2740     rmp.layoutoptions2 = layoutoptions2;
2741     rmp.layoutoptions3 = layoutoptions3;
2742     rmp.symmetry = symmetry;
2743     rmp.difficulty = difficulty;
2744     rmp.difficulty_given = difficulty_given;
2745     rmp.difficulty_increase = difficulty_increase;
2746     rmp.dungeon_level = dungeon_level;
2747     rmp.dungeon_depth = dungeon_depth;
2748     rmp.decoroptions = decoroptions;
2749     rmp.orientation = orientation;
2750     rmp.origin_y = origin_y;
2751     rmp.origin_x = origin_x;
2752     rmp.random_seed = random_seed;
2753 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2754 root 1.117 rmp.map_layout_style = map_layout_style;
2755     rmp.treasureoptions = treasureoptions;
2756     rmp.symmetry_used = symmetry_used;
2757     rmp.region = region;
2758 root 1.137 rmp.custom = custom;
2759 root 1.117
2760 root 1.140 RETVAL = self->generate_random_map (&rmp);
2761 root 1.117 }
2762     OUTPUT:
2763     RETVAL
2764    
2765 root 1.293 MODULE = cf PACKAGE = cf::mapspace
2766    
2767     INCLUDE: $PERL $srcdir/genacc mapspace ../include/map.h |
2768    
2769 root 1.19 MODULE = cf PACKAGE = cf::arch
2770 root 1.1
2771 root 1.218 int archetypes_size ()
2772     CODE:
2773     RETVAL = archetypes.size ();
2774     OUTPUT: RETVAL
2775    
2776     archetype *archetypes (U32 index)
2777     CODE:
2778     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2779     OUTPUT: RETVAL
2780 root 1.1
2781 root 1.212 object *instantiate (archetype *arch)
2782     CODE:
2783     RETVAL = arch_to_object (arch);
2784     OUTPUT:
2785     RETVAL
2786    
2787 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2788 root 1.1
2789 root 1.19 MODULE = cf PACKAGE = cf::party
2790 root 1.1
2791 root 1.19 partylist *first ()
2792 root 1.1 PROTOTYPE:
2793 root 1.19 CODE:
2794     RETVAL = get_firstparty ();
2795     OUTPUT: RETVAL
2796 root 1.1
2797 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2798 root 1.1
2799 root 1.19 MODULE = cf PACKAGE = cf::region
2800 root 1.1
2801 root 1.161 void
2802     list ()
2803     PPCODE:
2804     for_all_regions (rgn)
2805     XPUSHs (sv_2mortal (to_sv (rgn)));
2806    
2807 root 1.183 region *find (utf8_string name)
2808 root 1.161 PROTOTYPE: $
2809 root 1.19 CODE:
2810 root 1.161 RETVAL = region::find (name);
2811 root 1.19 OUTPUT: RETVAL
2812 root 1.1
2813 root 1.186 int specificity (region *rgn)
2814     CODE:
2815     RETVAL = 0;
2816     while (rgn = rgn->parent)
2817     RETVAL++;
2818     OUTPUT: RETVAL
2819    
2820 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2821 root 1.1
2822 root 1.19 MODULE = cf PACKAGE = cf::living
2823 root 1.1
2824 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2825 root 1.1
2826 root 1.76 MODULE = cf PACKAGE = cf::settings
2827    
2828 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2829 root 1.76
2830 root 1.84 MODULE = cf PACKAGE = cf::client
2831 root 1.79
2832 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2833 root 1.79
2834 root 1.84 int invoke (client *ns, int event, ...)
2835 root 1.79 CODE:
2836 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2837 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2838     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2839 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2840 root 1.79 OUTPUT: RETVAL
2841    
2842 root 1.84 SV *registry (client *ns)
2843 root 1.79
2844 root 1.100 void
2845     list ()
2846     PPCODE:
2847     EXTEND (SP, clients.size ());
2848     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2849     PUSHs (sv_2mortal (to_sv (*i)));
2850    
2851 root 1.88 void
2852 root 1.100 client::send_packet (SV *packet)
2853     CODE:
2854     {
2855     STRLEN len;
2856     char *buf = SvPVbyte (packet, len);
2857    
2858 root 1.258 if (len > MAXSOCKBUF)
2859     {
2860     // ugly
2861     if (THIS->pl)
2862     THIS->pl->failmsg ("[packet too long for client]");
2863     }
2864     else
2865     THIS->send_packet (buf, len);
2866 root 1.100 }
2867    
2868 root 1.237 faceidx
2869 root 1.238 client::need_face (utf8_string name, int pri = 0)
2870 root 1.237 CODE:
2871 root 1.238 RETVAL = face_find (name, 0);
2872     if (RETVAL)
2873     {
2874     THIS->send_face (RETVAL, pri);
2875     THIS->flush_fx ();
2876     }
2877     OUTPUT:
2878     RETVAL
2879    
2880     int
2881     client::fx_want (int idx, int value = -1)
2882     CODE:
2883     if (0 < idx && idx < FT_NUM)
2884     {
2885     RETVAL = THIS->fx_want [idx];
2886     if (items > 2)
2887     THIS->fx_want [idx] = value;
2888     }
2889     else
2890     RETVAL = 0;
2891 root 1.237 OUTPUT:
2892     RETVAL
2893    
2894 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2895    
2896     faceidx sound_find (utf8_string name)
2897    
2898 root 1.240 void sound_set (utf8_string str, faceidx face)
2899    
2900     # dire hack
2901     void old_sound_index (int idx, faceidx face)
2902     CODE:
2903     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2904     old_sound_index [idx] = face;
2905    
2906 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2907    
2908 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2909 root 1.176
2910 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2911 root 1.176
2912 root 1.183 faceidx alloc (utf8_string name)
2913 root 1.176 CODE:
2914     {
2915     do
2916     {
2917     RETVAL = faces.size ();
2918 root 1.177 faces.resize (RETVAL + 1);
2919 root 1.176 }
2920     while (!RETVAL); // crude way to leave index 0
2921    
2922     faces [RETVAL].name = name;
2923     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2924    
2925     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2926     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2927     }
2928     OUTPUT: RETVAL
2929    
2930 root 1.227 void set_type (faceidx idx, int value)
2931     ALIAS:
2932     set_type = 0
2933     set_visibility = 1
2934     set_magicmap = 2
2935     set_smooth = 3
2936     set_smoothlevel = 4
2937 root 1.176 CODE:
2938 root 1.229 faceinfo *f = face_info (idx); assert (f);
2939 root 1.227 switch (ix)
2940     {
2941     case 0: f->type = value; break;
2942     case 1: f->visibility = value; break;
2943     case 2: f->magicmap = value; break;
2944     case 3: f->smooth = value; break;
2945     case 4: f->smoothlevel = value; break;
2946     }
2947 root 1.177
2948     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2949 root 1.176 CODE:
2950 root 1.182 {
2951 root 1.231 faceinfo *f = face_info (idx); assert (f);
2952     facedata *d = &(faceset ? f->data64 : f->data32);
2953 root 1.181 sv_to (data, d->data);
2954     STRLEN clen;
2955     char *cdata = SvPVbyte (chksum, clen);
2956 root 1.182 clen = min (CHKSUM_SIZE, clen);
2957    
2958     if (memcmp (d->chksum, cdata, clen))
2959     {
2960     memcpy (d->chksum, cdata, clen);
2961    
2962     // invalidate existing client face info
2963     for_all_clients (ns)
2964     if (ns->faceset == faceset)
2965     {
2966     ns->faces_sent [idx] = false;
2967     ns->force_newmap = true;
2968     }
2969     }
2970     }
2971 root 1.176
2972 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2973     CODE:
2974 root 1.267 facedata *d = face_data (idx, faceset);
2975     if (!d) XSRETURN_UNDEF;
2976 root 1.229 RETVAL = d->data.size ();
2977     OUTPUT:
2978     RETVAL
2979    
2980     SV *get_chksum (faceidx idx, int faceset = 0)
2981     CODE:
2982 root 1.267 facedata *d = face_data (idx, faceset);
2983     if (!d) XSRETURN_UNDEF;
2984 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2985     OUTPUT:
2986     RETVAL
2987    
2988 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2989     CODE:
2990     facedata *d = face_data (idx, faceset);
2991     if (!d) XSRETURN_UNDEF;
2992     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2993     OUTPUT:
2994     RETVAL
2995    
2996 root 1.177 void invalidate (faceidx idx)
2997     CODE:
2998     for_all_clients (ns)
2999 root 1.182 {
3000     ns->faces_sent [idx] = false;
3001     ns->force_newmap = true;
3002     }
3003 root 1.177
3004     void invalidate_all ()
3005     CODE:
3006     for_all_clients (ns)
3007 root 1.182 {
3008     ns->faces_sent.reset ();
3009     ns->force_newmap = true;
3010     }
3011 root 1.177
3012 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
3013    
3014     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
3015    
3016     animidx anim_find (utf8_string name)
3017     CODE:
3018     RETVAL = animation::find (name).number;
3019     OUTPUT: RETVAL
3020    
3021     animidx set (utf8_string name, SV *frames, int facings = 1)
3022     CODE:
3023     {
3024     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
3025     croak ("frames must be an arrayref");
3026    
3027     AV *av = (AV *)SvRV (frames);
3028    
3029     animation *anim = &animation::find (name);
3030     if (anim->number)
3031     {
3032     anim->resize (av_len (av) + 1);
3033     anim->facings = facings;
3034     }
3035     else
3036     anim = &animation::create (name, av_len (av) + 1, facings);
3037    
3038     for (int i = 0; i < anim->num_animations; ++i)
3039     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
3040     }
3041     OUTPUT: RETVAL
3042    
3043     void invalidate_all ()
3044     CODE:
3045     for_all_clients (ns)
3046     ns->anims_sent.reset ();
3047    
3048 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
3049    
3050     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
3051    
3052     SV *
3053     new (char *klass)
3054     CODE:
3055     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
3056     OUTPUT: RETVAL
3057    
3058     void
3059     DESTROY (SV *sv)
3060     CODE:
3061     object_freezer *self;
3062     sv_to (sv, self);
3063     delete self;
3064    
3065     MODULE = cf PACKAGE = cf::object::thawer
3066    
3067     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
3068    
3069     SV *
3070     new_from_file (char *klass, octet_string path)
3071     CODE:
3072     object_thawer *f = new object_thawer (path);
3073     if (!*f)
3074     {
3075     delete f;
3076     XSRETURN_UNDEF;
3077     }
3078     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
3079     OUTPUT: RETVAL
3080    
3081     void
3082     DESTROY (SV *sv)
3083     CODE:
3084     object_thawer *self;
3085     sv_to (sv, self);
3086     delete self;
3087    
3088 root 1.252 void
3089 root 1.253 extract_tags (object_thawer *self)
3090 root 1.254 PPCODE:
3091 root 1.252 while (self->kw != KW_EOF)
3092     {
3093 root 1.254 PUTBACK;
3094 root 1.272 coroapi::cede_to_tick ();
3095 root 1.254 SPAGAIN;
3096 root 1.253
3097 root 1.252 if (self->kw == KW_tag)
3098 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
3099 root 1.252
3100     self->skip ();
3101     }
3102