ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.279
Committed: Sun Apr 20 06:20:38 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.278: +32 -25 lines
Log Message:
*** empty log message ***

File Contents

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