ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.284
Committed: Sat May 3 11:14:50 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.283: +7 -2 lines
Log Message:
kv rewrite

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.284 shstr
2056     object::kv_get (shstr key)
2057 root 1.1
2058 root 1.284 void
2059     object::kv_del (shstr key)
2060    
2061     void
2062     object::kv_set (shstr key, shstr value)
2063 root 1.1
2064     object *get_nearest_player (object *ob)
2065     ALIAS: nearest_player = 0
2066     PREINIT:
2067     extern object *get_nearest_player (object *);
2068    
2069     void rangevector (object *ob, object *other, int flags = 0)
2070     PROTOTYPE: $$;$
2071     PPCODE:
2072     {
2073     rv_vector rv;
2074     get_rangevector (ob, other, &rv, flags);
2075     EXTEND (SP, 5);
2076     PUSHs (newSVuv (rv.distance));
2077     PUSHs (newSViv (rv.distance_x));
2078     PUSHs (newSViv (rv.distance_y));
2079     PUSHs (newSViv (rv.direction));
2080 root 1.257 PUSHs (to_sv (rv.part));
2081 root 1.1 }
2082    
2083     bool on_same_map_as (object *ob, object *other)
2084     CODE:
2085     RETVAL = on_same_map (ob, other);
2086     OUTPUT: RETVAL
2087    
2088 root 1.183 const_utf8_string
2089 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2090 root 1.1 CODE:
2091 root 1.58 RETVAL = query_base_name (op, plural);
2092 root 1.1 OUTPUT: RETVAL
2093    
2094 root 1.256 # return the tail of an object, excluding itself
2095     void
2096     tail (object *op)
2097     PPCODE:
2098     while ((op = op->more))
2099     XPUSHs (sv_2mortal (to_sv (op)));
2100    
2101 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2102    
2103     player *player (object *op)
2104     CODE:
2105     RETVAL = op->contr;
2106     OUTPUT: RETVAL
2107    
2108 root 1.257 bool move_player (object *op, int dir)
2109    
2110 root 1.105 void check_score (object *op)
2111    
2112 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2113 root 1.120 CODE:
2114     new_draw_info (flags, 0, op, txt);
2115 root 1.1
2116     void kill_player (object *op)
2117    
2118 root 1.257 void esrv_send_item (object *pl, object *item)
2119    
2120     void esrv_update_item (object *pl, int what, object *item)
2121     C_ARGS: what, pl, item
2122    
2123     void esrv_del_item (object *pl, int tag)
2124     C_ARGS: pl->contr, tag
2125 root 1.58
2126 root 1.183 int command_summon (object *op, utf8_string params)
2127 root 1.67
2128 root 1.183 int command_arrest (object *op, utf8_string params)
2129 root 1.67
2130 root 1.66
2131 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2132 root 1.1
2133 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2134 root 1.62
2135 root 1.18 int invoke (player *pl, int event, ...)
2136     CODE:
2137     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2138 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2139     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2140 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2141 root 1.18 OUTPUT: RETVAL
2142    
2143 root 1.12 SV *registry (player *pl)
2144 root 1.1
2145 root 1.102 void
2146     save_stats (player *pl)
2147     CODE:
2148     pl->ob->stats.hp = pl->ob->stats.maxhp;
2149     pl->ob->stats.sp = pl->ob->stats.maxsp;
2150     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2151     pl->orig_stats = pl->ob->stats;
2152    
2153 root 1.217 void clear_los (player *pl)
2154    
2155 root 1.1 bool
2156     cell_visible (player *pl, int dx, int dy)
2157     CODE:
2158 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2159     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2160 root 1.1 OUTPUT:
2161     RETVAL
2162    
2163 root 1.4 void
2164 root 1.1 send (player *pl, SV *packet)
2165     CODE:
2166     {
2167     STRLEN len;
2168     char *buf = SvPVbyte (packet, len);
2169    
2170 root 1.258 if (len > MAXSOCKBUF)
2171     pl->failmsg ("[packet too long for client]");
2172     else if (pl->ns)
2173 root 1.100 pl->ns->send_packet (buf, len);
2174 root 1.1 }
2175    
2176     int
2177     listening (player *pl, int new_value = -1)
2178     CODE:
2179     RETVAL = pl->listening;
2180     if (new_value >= 0)
2181     pl->listening = new_value;
2182     OUTPUT:
2183     RETVAL
2184    
2185 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2186 root 1.45 PROTOTYPE: $;$$$
2187 root 1.1 PPCODE:
2188 root 1.45 if (GIMME_V != G_VOID)
2189     {
2190     EXTEND (SP, 3);
2191     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2192     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2193     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2194     }
2195 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2196     if (x) sv_to (x, pl->bed_x);
2197     if (y) sv_to (y, pl->bed_y);
2198 root 1.1
2199     void
2200     list ()
2201     PPCODE:
2202 root 1.128 for_all_players (pl)
2203 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2204 root 1.1
2205    
2206     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2207    
2208 root 1.61 int invoke (maptile *map, int event, ...)
2209 root 1.18 CODE:
2210     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2211 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2212     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2213 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2214 root 1.25 OUTPUT: RETVAL
2215 root 1.18
2216 root 1.61 SV *registry (maptile *map)
2217 root 1.12
2218 root 1.255 void
2219     find_tagged_objects (maptile *map, utf8_string tag = 0)
2220     PPCODE:
2221     {
2222     if (!map->spaces)
2223     XSRETURN_EMPTY;
2224    
2225     if (tag)
2226     {
2227     shstr_cmp tag_ (tag);
2228    
2229     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2230     for (object *op = ms->bot; op; op = op->above)
2231     if (op->tag == tag_)
2232     XPUSHs (sv_2mortal (to_sv (op)));
2233     }
2234     else
2235     {
2236     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2237     for (object *op = ms->bot; op; op = op->above)
2238     if (op->tag)
2239     XPUSHs (sv_2mortal (to_sv (op)));
2240     }
2241     }
2242    
2243 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2244 root 1.1
2245 root 1.116 void
2246     maptile::instantiate ()
2247    
2248     maptile *new ()
2249 root 1.1 PROTOTYPE:
2250     CODE:
2251 root 1.116 RETVAL = new maptile;
2252 root 1.1 OUTPUT:
2253     RETVAL
2254    
2255 root 1.116 void
2256 root 1.117 maptile::players ()
2257     PPCODE:
2258     if (GIMME_V == G_SCALAR)
2259 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2260 root 1.117 else if (GIMME_V == G_ARRAY)
2261     {
2262     EXTEND (SP, THIS->players);
2263     for_all_players (pl)
2264     if (pl->ob && pl->ob->map == THIS)
2265 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2266 root 1.117 }
2267    
2268 root 1.156 void
2269 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2270 root 1.156 CODE:
2271     {
2272 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2273     croak ("maptile::add_underlay: palette must be arrayref");
2274 root 1.156
2275 root 1.168 palette = SvRV (palette);
2276 root 1.156
2277 root 1.168 STRLEN idxlen;
2278     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2279 root 1.156
2280 root 1.168 for (int x = 0; x < THIS->width; ++x)
2281     for (int y = 0; y < THIS->height; ++y)
2282     {
2283     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2284     if (op->flag [FLAG_IS_FLOOR])
2285     goto skip_space;
2286    
2287     {
2288     int offs = offset + y * stride + x;
2289     if (IN_RANGE_EXC (offs, 0, idxlen))
2290     {
2291     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2292     {
2293     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2294     ob->flag [FLAG_NO_MAP_SAVE] = true;
2295     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2296 root 1.200
2297     if (ob->randomitems)
2298     {
2299 root 1.203 if (!ob->above)
2300     {
2301     ob->create_treasure (ob->randomitems);
2302    
2303     for (object *op = ob->above; op; op = op->above)
2304     op->flag [FLAG_NO_MAP_SAVE] = true;
2305     }
2306    
2307 root 1.200 ob->randomitems = 0;
2308     }
2309 root 1.168 }
2310     }
2311     }
2312 root 1.156
2313 root 1.168 skip_space: ;
2314     }
2315     }
2316    
2317     void
2318     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2319     CODE:
2320     {
2321     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2322     croak ("maptile::set_regiondata: palette must be arrayref");
2323    
2324     palette = SvRV (palette);
2325    
2326     STRLEN idxlen;
2327     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2328    
2329 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2330 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2331    
2332     for (int i = av_len ((AV *)palette) + 1; i--; )
2333 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2334 root 1.168
2335     for (int y = 0; y < THIS->height; ++y)
2336     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2337    
2338     sfree (THIS->regions, THIS->size ());
2339 root 1.230 delete [] THIS->regionmap;
2340 root 1.168
2341     THIS->regions = regions;
2342 root 1.156 THIS->regionmap = regionmap;
2343     }
2344    
2345 root 1.193 void
2346     maptile::create_region_treasure ()
2347     CODE:
2348     {
2349     object *op = object::create ();
2350     op->type = FLOOR;
2351     op->map = THIS;
2352    
2353     for (int x = 0; x < THIS->width; ++x)
2354     for (int y = 0; y < THIS->height; ++y)
2355     {
2356     region *rgn = THIS->region (x, y);
2357    
2358     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2359     if (rgn->treasure && rndm () < rgn->treasure_density)
2360     {
2361     op->x = x;
2362     op->y = y;
2363     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2364     }
2365     }
2366    
2367     op->destroy ();
2368     }
2369    
2370 root 1.74 int out_of_map (maptile *map, int x, int y)
2371    
2372 root 1.29 void
2373 root 1.61 trigger (maptile *map, long connection, bool state = true)
2374 root 1.29 CODE:
2375     activate_connection (map, connection, state);
2376    
2377     void
2378 root 1.61 get_connection (maptile *map, long connection)
2379 root 1.29 PPCODE:
2380     oblinkpt *obp = get_connection_links (map, connection);
2381     if (obp)
2382     for (objectlink *ol = obp->link; ol; ol = ol->next)
2383 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2384 root 1.1
2385     void
2386 root 1.140 get_map_flags (maptile *map, int x, int y)
2387 root 1.1 PPCODE:
2388     {
2389 root 1.61 maptile *nmap = 0;
2390 root 1.1 I16 nx = 0, ny = 0;
2391 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2392 root 1.1
2393     EXTEND (SP, 4);
2394     PUSHs (sv_2mortal (newSViv (flags)));
2395    
2396     if (GIMME_V == G_ARRAY)
2397     {
2398 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2399 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2400     PUSHs (sv_2mortal (newSViv (ny)));
2401     }
2402     }
2403    
2404     void
2405 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2406 root 1.1 PROTOTYPE: $$$
2407     PPCODE:
2408     {
2409     object *o;
2410 root 1.61 maptile *nmap = 0;
2411 root 1.1 I16 nx, ny;
2412    
2413 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2414 root 1.1
2415     if (nmap)
2416     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2417 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2418 root 1.1 }
2419    
2420     SV *
2421 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2422 root 1.1 PROTOTYPE: $$$
2423     ALIAS:
2424     top_at = 1
2425     flags_at = 2
2426     light_at = 3
2427     move_block_at = 4
2428     move_slow_at = 5
2429     move_on_at = 6
2430     move_off_at = 7
2431     INIT:
2432 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2433 root 1.1 CODE:
2434     switch (ix)
2435     {
2436 root 1.257 case 0: RETVAL = to_sv (GET_MAP_OB (obj, x, y)); break;
2437     case 1: RETVAL = to_sv (GET_MAP_TOP (obj, x, y)); break;
2438     case 2: RETVAL = newSVuv (GET_MAP_FLAGS (obj, x, y)); break;
2439     case 3: RETVAL = newSViv (GET_MAP_LIGHT (obj, x, y)); break;
2440     case 4: RETVAL = newSVuv (GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2441     case 5: RETVAL = newSVuv (GET_MAP_MOVE_SLOW (obj, x, y)); break;
2442     case 6: RETVAL = newSVuv (GET_MAP_MOVE_ON (obj, x, y)); break;
2443     case 7: RETVAL = newSVuv (GET_MAP_MOVE_OFF (obj, x, y)); break;
2444 root 1.1 }
2445 root 1.122 OUTPUT: RETVAL
2446 root 1.1
2447 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2448    
2449     void fix_walls_around (maptile *map, int x, int y)
2450 root 1.1
2451 root 1.117 # worst xs function of my life
2452 root 1.140 bool
2453 root 1.117 _create_random_map (\
2454 root 1.140 maptile *self,\
2455 root 1.183 utf8_string wallstyle,\
2456     utf8_string wall_name,\
2457     utf8_string floorstyle,\
2458     utf8_string monsterstyle,\
2459     utf8_string treasurestyle,\
2460     utf8_string layoutstyle,\
2461     utf8_string doorstyle,\
2462     utf8_string decorstyle,\
2463     utf8_string origin_map,\
2464     utf8_string final_map,\
2465     utf8_string exitstyle,\
2466     utf8_string this_map,\
2467     utf8_string exit_on_final_map,\
2468 root 1.146 int xsize,\
2469     int ysize,\
2470 root 1.117 int expand2x,\
2471     int layoutoptions1,\
2472     int layoutoptions2,\
2473     int layoutoptions3,\
2474     int symmetry,\
2475     int difficulty,\
2476     int difficulty_given,\
2477     float difficulty_increase,\
2478     int dungeon_level,\
2479     int dungeon_depth,\
2480     int decoroptions,\
2481     int orientation,\
2482     int origin_y,\
2483     int origin_x,\
2484 root 1.146 U32 random_seed,\
2485 root 1.117 val64 total_map_hp,\
2486     int map_layout_style,\
2487     int treasureoptions,\
2488     int symmetry_used,\
2489 root 1.137 region *region,\
2490 root 1.183 utf8_string custom\
2491 root 1.117 )
2492     CODE:
2493     {
2494     random_map_params rmp;
2495    
2496     assign (rmp.wallstyle , wallstyle);
2497     assign (rmp.wall_name , wall_name);
2498     assign (rmp.floorstyle , floorstyle);
2499     assign (rmp.monsterstyle , monsterstyle);
2500     assign (rmp.treasurestyle , treasurestyle);
2501     assign (rmp.layoutstyle , layoutstyle);
2502     assign (rmp.doorstyle , doorstyle);
2503     assign (rmp.decorstyle , decorstyle);
2504     assign (rmp.exitstyle , exitstyle);
2505     assign (rmp.exit_on_final_map, exit_on_final_map);
2506    
2507 root 1.122 rmp.origin_map = origin_map;
2508     rmp.final_map = final_map;
2509     rmp.this_map = this_map;
2510 root 1.146 rmp.xsize = xsize;
2511     rmp.ysize = ysize;
2512 root 1.117 rmp.expand2x = expand2x;
2513     rmp.layoutoptions1 = layoutoptions1;
2514     rmp.layoutoptions2 = layoutoptions2;
2515     rmp.layoutoptions3 = layoutoptions3;
2516     rmp.symmetry = symmetry;
2517     rmp.difficulty = difficulty;
2518     rmp.difficulty_given = difficulty_given;
2519     rmp.difficulty_increase = difficulty_increase;
2520     rmp.dungeon_level = dungeon_level;
2521     rmp.dungeon_depth = dungeon_depth;
2522     rmp.decoroptions = decoroptions;
2523     rmp.orientation = orientation;
2524     rmp.origin_y = origin_y;
2525     rmp.origin_x = origin_x;
2526     rmp.random_seed = random_seed;
2527 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2528 root 1.117 rmp.map_layout_style = map_layout_style;
2529     rmp.treasureoptions = treasureoptions;
2530     rmp.symmetry_used = symmetry_used;
2531     rmp.region = region;
2532 root 1.137 rmp.custom = custom;
2533 root 1.117
2534 root 1.140 RETVAL = self->generate_random_map (&rmp);
2535 root 1.117 }
2536     OUTPUT:
2537     RETVAL
2538    
2539 root 1.19 MODULE = cf PACKAGE = cf::arch
2540 root 1.1
2541 root 1.218 int archetypes_size ()
2542     CODE:
2543     RETVAL = archetypes.size ();
2544     OUTPUT: RETVAL
2545    
2546     archetype *archetypes (U32 index)
2547     CODE:
2548     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2549     OUTPUT: RETVAL
2550 root 1.1
2551 root 1.212 object *instantiate (archetype *arch)
2552     CODE:
2553     RETVAL = arch_to_object (arch);
2554     OUTPUT:
2555     RETVAL
2556    
2557 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2558 root 1.1
2559 root 1.19 MODULE = cf PACKAGE = cf::party
2560 root 1.1
2561 root 1.19 partylist *first ()
2562 root 1.1 PROTOTYPE:
2563 root 1.19 CODE:
2564     RETVAL = get_firstparty ();
2565     OUTPUT: RETVAL
2566 root 1.1
2567 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2568 root 1.1
2569 root 1.19 MODULE = cf PACKAGE = cf::region
2570 root 1.1
2571 root 1.161 void
2572     list ()
2573     PPCODE:
2574     for_all_regions (rgn)
2575     XPUSHs (sv_2mortal (to_sv (rgn)));
2576    
2577 root 1.183 region *find (utf8_string name)
2578 root 1.161 PROTOTYPE: $
2579 root 1.19 CODE:
2580 root 1.161 RETVAL = region::find (name);
2581 root 1.19 OUTPUT: RETVAL
2582 root 1.1
2583 root 1.183 region *find_fuzzy (utf8_string name)
2584 root 1.122 PROTOTYPE: $
2585     CODE:
2586 root 1.161 RETVAL = region::find_fuzzy (name);
2587 root 1.122 OUTPUT: RETVAL
2588    
2589 root 1.186 int specificity (region *rgn)
2590     CODE:
2591     RETVAL = 0;
2592     while (rgn = rgn->parent)
2593     RETVAL++;
2594     OUTPUT: RETVAL
2595    
2596 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2597 root 1.1
2598 root 1.19 MODULE = cf PACKAGE = cf::living
2599 root 1.1
2600 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2601 root 1.1
2602 root 1.76 MODULE = cf PACKAGE = cf::settings
2603    
2604 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2605 root 1.76
2606 root 1.84 MODULE = cf PACKAGE = cf::client
2607 root 1.79
2608 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2609 root 1.79
2610 root 1.84 int invoke (client *ns, int event, ...)
2611 root 1.79 CODE:
2612 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2613 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2614     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2615 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2616 root 1.79 OUTPUT: RETVAL
2617    
2618 root 1.84 SV *registry (client *ns)
2619 root 1.79
2620 root 1.100 void
2621     list ()
2622     PPCODE:
2623     EXTEND (SP, clients.size ());
2624     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2625     PUSHs (sv_2mortal (to_sv (*i)));
2626    
2627 root 1.88 void
2628 root 1.100 client::send_packet (SV *packet)
2629     CODE:
2630     {
2631     STRLEN len;
2632     char *buf = SvPVbyte (packet, len);
2633    
2634 root 1.258 if (len > MAXSOCKBUF)
2635     {
2636     // ugly
2637     if (THIS->pl)
2638     THIS->pl->failmsg ("[packet too long for client]");
2639     }
2640     else
2641     THIS->send_packet (buf, len);
2642 root 1.100 }
2643    
2644 root 1.237 faceidx
2645 root 1.238 client::need_face (utf8_string name, int pri = 0)
2646 root 1.237 CODE:
2647 root 1.238 RETVAL = face_find (name, 0);
2648     if (RETVAL)
2649     {
2650     THIS->send_face (RETVAL, pri);
2651     THIS->flush_fx ();
2652     }
2653     OUTPUT:
2654     RETVAL
2655    
2656     int
2657     client::fx_want (int idx, int value = -1)
2658     CODE:
2659     if (0 < idx && idx < FT_NUM)
2660     {
2661     RETVAL = THIS->fx_want [idx];
2662     if (items > 2)
2663     THIS->fx_want [idx] = value;
2664     }
2665     else
2666     RETVAL = 0;
2667 root 1.237 OUTPUT:
2668     RETVAL
2669    
2670 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2671    
2672     faceidx sound_find (utf8_string name)
2673    
2674 root 1.240 void sound_set (utf8_string str, faceidx face)
2675    
2676     # dire hack
2677     void old_sound_index (int idx, faceidx face)
2678     CODE:
2679     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2680     old_sound_index [idx] = face;
2681    
2682 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2683    
2684 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2685 root 1.176
2686 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2687 root 1.176
2688 root 1.183 faceidx alloc (utf8_string name)
2689 root 1.176 CODE:
2690     {
2691     do
2692     {
2693     RETVAL = faces.size ();
2694 root 1.177 faces.resize (RETVAL + 1);
2695 root 1.176 }
2696     while (!RETVAL); // crude way to leave index 0
2697    
2698     faces [RETVAL].name = name;
2699     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2700    
2701     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2702     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2703     }
2704     OUTPUT: RETVAL
2705    
2706 root 1.227 void set_type (faceidx idx, int value)
2707     ALIAS:
2708     set_type = 0
2709     set_visibility = 1
2710     set_magicmap = 2
2711     set_smooth = 3
2712     set_smoothlevel = 4
2713 root 1.176 CODE:
2714 root 1.229 faceinfo *f = face_info (idx); assert (f);
2715 root 1.227 switch (ix)
2716     {
2717     case 0: f->type = value; break;
2718     case 1: f->visibility = value; break;
2719     case 2: f->magicmap = value; break;
2720     case 3: f->smooth = value; break;
2721     case 4: f->smoothlevel = value; break;
2722     }
2723 root 1.177
2724     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2725 root 1.176 CODE:
2726 root 1.182 {
2727 root 1.231 faceinfo *f = face_info (idx); assert (f);
2728     facedata *d = &(faceset ? f->data64 : f->data32);
2729 root 1.181 sv_to (data, d->data);
2730     STRLEN clen;
2731     char *cdata = SvPVbyte (chksum, clen);
2732 root 1.182 clen = min (CHKSUM_SIZE, clen);
2733    
2734     if (memcmp (d->chksum, cdata, clen))
2735     {
2736     memcpy (d->chksum, cdata, clen);
2737    
2738     // invalidate existing client face info
2739     for_all_clients (ns)
2740     if (ns->faceset == faceset)
2741     {
2742     ns->faces_sent [idx] = false;
2743     ns->force_newmap = true;
2744     }
2745     }
2746     }
2747 root 1.176
2748 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2749     CODE:
2750 root 1.267 facedata *d = face_data (idx, faceset);
2751     if (!d) XSRETURN_UNDEF;
2752 root 1.229 RETVAL = d->data.size ();
2753     OUTPUT:
2754     RETVAL
2755    
2756     SV *get_chksum (faceidx idx, int faceset = 0)
2757     CODE:
2758 root 1.267 facedata *d = face_data (idx, faceset);
2759     if (!d) XSRETURN_UNDEF;
2760 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2761     OUTPUT:
2762     RETVAL
2763    
2764 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2765     CODE:
2766     facedata *d = face_data (idx, faceset);
2767     if (!d) XSRETURN_UNDEF;
2768     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2769     OUTPUT:
2770     RETVAL
2771    
2772 root 1.177 void invalidate (faceidx idx)
2773     CODE:
2774     for_all_clients (ns)
2775 root 1.182 {
2776     ns->faces_sent [idx] = false;
2777     ns->force_newmap = true;
2778     }
2779 root 1.177
2780     void invalidate_all ()
2781     CODE:
2782     for_all_clients (ns)
2783 root 1.182 {
2784     ns->faces_sent.reset ();
2785     ns->force_newmap = true;
2786     }
2787 root 1.177
2788 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2789    
2790     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2791    
2792     animidx anim_find (utf8_string name)
2793     CODE:
2794     RETVAL = animation::find (name).number;
2795     OUTPUT: RETVAL
2796    
2797     animidx set (utf8_string name, SV *frames, int facings = 1)
2798     CODE:
2799     {
2800     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2801     croak ("frames must be an arrayref");
2802    
2803     AV *av = (AV *)SvRV (frames);
2804    
2805     animation *anim = &animation::find (name);
2806     if (anim->number)
2807     {
2808     anim->resize (av_len (av) + 1);
2809     anim->facings = facings;
2810     }
2811     else
2812     anim = &animation::create (name, av_len (av) + 1, facings);
2813    
2814     for (int i = 0; i < anim->num_animations; ++i)
2815     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2816     }
2817     OUTPUT: RETVAL
2818    
2819     void invalidate_all ()
2820     CODE:
2821     for_all_clients (ns)
2822     ns->anims_sent.reset ();
2823    
2824 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2825    
2826     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2827    
2828     SV *
2829     new (char *klass)
2830     CODE:
2831     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2832     OUTPUT: RETVAL
2833    
2834     void
2835     DESTROY (SV *sv)
2836     CODE:
2837     object_freezer *self;
2838     sv_to (sv, self);
2839     delete self;
2840    
2841     MODULE = cf PACKAGE = cf::object::thawer
2842    
2843     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2844    
2845     SV *
2846     new_from_file (char *klass, octet_string path)
2847     CODE:
2848     object_thawer *f = new object_thawer (path);
2849     if (!*f)
2850     {
2851     delete f;
2852     XSRETURN_UNDEF;
2853     }
2854     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2855     OUTPUT: RETVAL
2856    
2857     void
2858     DESTROY (SV *sv)
2859     CODE:
2860     object_thawer *self;
2861     sv_to (sv, self);
2862     delete self;
2863    
2864 root 1.252 void
2865 root 1.253 extract_tags (object_thawer *self)
2866 root 1.254 PPCODE:
2867 root 1.252 while (self->kw != KW_EOF)
2868     {
2869 root 1.254 PUTBACK;
2870 root 1.272 coroapi::cede_to_tick ();
2871 root 1.254 SPAGAIN;
2872 root 1.253
2873 root 1.252 if (self->kw == KW_tag)
2874 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
2875 root 1.252
2876     self->skip ();
2877     }
2878