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