ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.283
Committed: Wed Apr 30 08:29:31 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.282: +5 -0 lines
Log Message:
*** empty log message ***

File Contents

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