ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.275
Committed: Fri Apr 11 13:59:06 2008 UTC (16 years, 2 months ago) by root
Branch: MAIN
Changes since 1.274: +20 -23 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     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1408    
1409     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1410     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1411    
1412 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1413    
1414 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1415    
1416     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1417 root 1.99
1418 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1419 root 1.117
1420     // random map generator
1421 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1422     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1423    
1424     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1425     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1426     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1427    
1428     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1429     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1430 root 1.195
1431     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1432     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1433     const_iv (GT_MINIMAL)
1434 root 1.238
1435     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1436     const_iv (FT_RSRC) const_iv (FT_NUM)
1437 root 1.1 };
1438    
1439     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1440 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1441 root 1.1
1442     static const struct {
1443     const char *name;
1444 root 1.14 int skip;
1445 root 1.7 IV klass;
1446 root 1.1 IV iv;
1447 root 1.6 } *eiv, event_iv[] = {
1448 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1449 root 1.6 # include "eventinc.h"
1450     # undef def
1451     };
1452    
1453     AV *av = get_av ("cf::EVENT", 1);
1454    
1455     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1456 root 1.7 {
1457     AV *event = newAV ();
1458 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1459 root 1.7 av_push (event, newSViv (eiv->klass));
1460     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1461 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1462 root 1.7 }
1463 root 1.14 }
1464    
1465 root 1.109 void _connect_to_perl ()
1466 root 1.14
1467 root 1.210 void _recalc_want ()
1468    
1469 root 1.47 void _global_reattach ()
1470 root 1.14 CODE:
1471     {
1472     // reattach to all attachable objects in the game.
1473 root 1.128 for_all_clients (ns)
1474     ns->reattach ();
1475 root 1.96
1476 root 1.128 for_all_objects (op)
1477 root 1.109 op->reattach ();
1478 root 1.1 }
1479    
1480 root 1.192 # support function for map-world.ext
1481     void _quantise (SV *data_sv, SV *plt_sv)
1482     CODE:
1483     {
1484     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1485     croak ("_quantise called with invalid agruments");
1486    
1487     plt_sv = SvRV (plt_sv);
1488     SV **plt = AvARRAY (plt_sv);
1489     int plt_count = AvFILL (plt_sv) + 1;
1490    
1491     STRLEN len;
1492     char *data = SvPVbyte (data_sv, len);
1493     char *dst = data;
1494    
1495     while (len >= 3)
1496     {
1497     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1498     {
1499     char *val = SvPVX (*val_sv);
1500    
1501     if (val [0] == data [0]
1502     && val [1] == data [1]
1503     && val [2] == data [2])
1504     {
1505     *dst++ = val [3];
1506     goto next;
1507     }
1508     }
1509    
1510     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1511     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1512     dst - SvPVX (data_sv), len);
1513    
1514     next:
1515     data += 3;
1516     len -= 3;
1517     }
1518    
1519     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1520     }
1521    
1522 root 1.273 void evthread_start (int aiofd)
1523 root 1.272
1524     void cede_to_tick ()
1525 root 1.236 CODE:
1526 root 1.272 coroapi::cede_to_tick ();
1527 root 1.236
1528 root 1.272 NV till_tick ()
1529 root 1.236 CODE:
1530 root 1.272 RETVAL = SvNVX (sv_next_tick) - now ();
1531 root 1.236 OUTPUT:
1532     RETVAL
1533    
1534 root 1.272 int tick_inhibit ()
1535 root 1.236 CODE:
1536 root 1.272 RETVAL = tick_inhibit;
1537 root 1.236 OUTPUT:
1538     RETVAL
1539    
1540 root 1.272 void tick_inhibit_inc ()
1541     CODE:
1542     ++tick_inhibit;
1543    
1544     void tick_inhibit_dec ()
1545     CODE:
1546     if (!--tick_inhibit)
1547     if (tick_pending)
1548     {
1549     ev_async_send (EV_DEFAULT, &tick_watcher);
1550     coroapi::cede ();
1551     }
1552    
1553     void server_tick ()
1554     CODE:
1555     {
1556     NOW = ev_now (EV_DEFAULT);
1557     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1558     SvNV_set (sv_tick_start, NOW); SvNOK_only (sv_tick_start);
1559     runtime = SvNVX (sv_runtime);
1560    
1561     server_tick ();
1562    
1563     NOW = ev_time ();
1564     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1565     runtime += TICK;
1566     SvNV_set (sv_runtime, runtime); SvNOK_only (sv_runtime);
1567     }
1568    
1569 root 1.1 NV floor (NV x)
1570    
1571     NV ceil (NV x)
1572    
1573 root 1.143 NV rndm (...)
1574     CODE:
1575     switch (items)
1576     {
1577     case 0: RETVAL = rndm (); break;
1578     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1579     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1580     default: croak ("cf::rndm requires none, one or two parameters."); break;
1581     }
1582     OUTPUT:
1583     RETVAL
1584    
1585 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1586     CODE:
1587     RETVAL = clamp (value, min_value, max_value);
1588     OUTPUT:
1589     RETVAL
1590    
1591     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1592     CODE:
1593     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1594     OUTPUT:
1595     RETVAL
1596    
1597 root 1.268 void weaken (...)
1598     PROTOTYPE: @
1599     CODE:
1600     while (items > 0)
1601     sv_rvweaken (ST (--items));
1602    
1603 root 1.1 void
1604 root 1.198 log_backtrace (utf8_string msg)
1605    
1606     void
1607     LOG (int flags, utf8_string msg)
1608 root 1.1 PROTOTYPE: $$
1609 root 1.198 C_ARGS: flags, "%s", msg
1610 root 1.1
1611 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1612 root 1.1 PROTOTYPE: $$
1613    
1614 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1615 root 1.1 PROTOTYPE: $$
1616    
1617     void
1618 root 1.259 mallinfo ()
1619     PPCODE:
1620     {
1621     #if __GLIBC__
1622     struct mallinfo mai = mallinfo ();
1623 root 1.260 EXTEND (SP, 10*2);
1624 root 1.259 PUSHs (sv_2mortal (newSVpv ("arena" , 0))); PUSHs (sv_2mortal (newSViv (mai.arena)));
1625     PUSHs (sv_2mortal (newSVpv ("ordblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.ordblks)));
1626 root 1.260 PUSHs (sv_2mortal (newSVpv ("smblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.smblks)));
1627 root 1.259 PUSHs (sv_2mortal (newSVpv ("hblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblks)));
1628     PUSHs (sv_2mortal (newSVpv ("hblkhd" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblkhd)));
1629 root 1.260 PUSHs (sv_2mortal (newSVpv ("usmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.usmblks)));
1630     PUSHs (sv_2mortal (newSVpv ("fsmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.fsmblks)));
1631 root 1.259 PUSHs (sv_2mortal (newSVpv ("uordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.uordblks)));
1632     PUSHs (sv_2mortal (newSVpv ("fordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.fordblks)));
1633     PUSHs (sv_2mortal (newSVpv ("keepcost", 0))); PUSHs (sv_2mortal (newSViv (mai.keepcost)));
1634     #endif
1635 root 1.261 EXTEND (SP, 2*2);
1636     PUSHs (sv_2mortal (newSVpv ("slice_alloc", 0))); PUSHs (sv_2mortal (newSVuv (slice_alloc)));
1637     PUSHs (sv_2mortal (newSVpv ("shstr_alloc", 0))); PUSHs (sv_2mortal (newSVuv (shstr_alloc)));
1638 root 1.259 }
1639    
1640     void
1641 root 1.1 sub_generation_inc ()
1642     CODE:
1643     PL_sub_generation++;
1644    
1645 root 1.183 const_octet_string
1646 root 1.1 mapdir ()
1647     PROTOTYPE:
1648     ALIAS:
1649     mapdir = 0
1650     uniquedir = 1
1651     tmpdir = 2
1652     confdir = 3
1653     localdir = 4
1654     playerdir = 5
1655     datadir = 6
1656     CODE:
1657 root 1.19 switch (ix)
1658     {
1659     case 0: RETVAL = settings.mapdir ; break;
1660     case 1: RETVAL = settings.uniquedir; break;
1661     case 2: RETVAL = settings.tmpdir ; break;
1662     case 3: RETVAL = settings.confdir ; break;
1663     case 4: RETVAL = settings.localdir ; break;
1664     case 5: RETVAL = settings.playerdir; break;
1665     case 6: RETVAL = settings.datadir ; break;
1666     }
1667 root 1.1 OUTPUT: RETVAL
1668    
1669 root 1.120 void abort ()
1670    
1671 root 1.199 void reset_signals ()
1672    
1673 root 1.270 void fork_abort (const_octet_string cause = "cf::fork_abort")
1674 root 1.144
1675 root 1.270 void cleanup (const_octet_string cause, bool make_core = false)
1676 root 1.134
1677 root 1.116 void emergency_save ()
1678    
1679 root 1.156 void _exit (int status = EXIT_SUCCESS)
1680    
1681 root 1.125 #if _POSIX_MEMLOCK
1682    
1683     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1684 root 1.271 INIT:
1685     mallopt (M_PERTURB, 0xaa); // bug-workaround for linux glibc+mlockall+calloc
1686 root 1.125
1687     int munlockall ()
1688    
1689     #endif
1690    
1691 root 1.183 int find_animation (utf8_string text)
1692 root 1.1 PROTOTYPE: $
1693    
1694 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1695 root 1.1
1696 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1697 root 1.1
1698     int
1699     exp_to_level (val64 exp)
1700     CODE:
1701     {
1702     int i = 0;
1703    
1704     RETVAL = settings.max_level;
1705    
1706     for (i = 1; i <= settings.max_level; i++)
1707     {
1708     if (levels[i] > exp)
1709     {
1710     RETVAL = i - 1;
1711     break;
1712     }
1713     }
1714     }
1715     OUTPUT: RETVAL
1716    
1717     val64
1718     level_to_min_exp (int level)
1719     CODE:
1720     if (level > settings.max_level)
1721     RETVAL = levels[settings.max_level];
1722     else if (level < 1)
1723     RETVAL = 0;
1724     else
1725     RETVAL = levels[level];
1726     OUTPUT: RETVAL
1727    
1728     SV *
1729     resistance_to_string (int atnr)
1730     CODE:
1731     if (atnr >= 0 && atnr < NROFATTACKS)
1732     RETVAL = newSVpv (resist_plus[atnr], 0);
1733     else
1734     XSRETURN_UNDEF;
1735     OUTPUT: RETVAL
1736    
1737 root 1.275 UUID
1738 root 1.274 uuid_cur ()
1739     CODE:
1740 root 1.275 RETVAL = UUID::cur;
1741 root 1.274 OUTPUT:
1742     RETVAL
1743    
1744 root 1.275 UUID
1745 root 1.274 uuid_gen ()
1746     CODE:
1747 root 1.275 RETVAL = UUID::gen ();
1748     OUTPUT:
1749     RETVAL
1750    
1751     val64
1752     uuid_seq (UUID uuid)
1753     CODE:
1754     RETVAL = uuid.seq;
1755     OUTPUT:
1756     RETVAL
1757    
1758     UUID
1759     uuid_str (val64 seq)
1760     CODE:
1761     RETVAL.seq = seq;
1762 root 1.274 OUTPUT:
1763     RETVAL
1764    
1765     void
1766     coin_names ()
1767     PPCODE:
1768     EXTEND (SP, NUM_COINS);
1769     for (int i = 0; i < NUM_COINS; ++i)
1770     PUSHs (sv_2mortal (newSVpv (coins [i], 0)));
1771    
1772     void
1773     coin_archetypes ()
1774     PPCODE:
1775     EXTEND (SP, NUM_COINS);
1776     for (int i = 0; i < NUM_COINS; ++i)
1777     PUSHs (sv_2mortal (to_sv (archetype::find (coins [i]))));
1778    
1779 root 1.162 bool
1780 root 1.183 load_resource_file (octet_string filename)
1781 root 1.162
1782 root 1.97 MODULE = cf PACKAGE = cf::attachable
1783    
1784 root 1.27 int
1785 root 1.97 valid (SV *obj)
1786 root 1.27 CODE:
1787     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1788     OUTPUT:
1789     RETVAL
1790    
1791 root 1.164 void
1792     debug_trace (attachable *obj, bool on = true)
1793     CODE:
1794     obj->flags &= ~attachable::F_DEBUG_TRACE;
1795     if (on)
1796     obj->flags |= attachable::F_DEBUG_TRACE;
1797    
1798 root 1.153 int mortals_size ()
1799     CODE:
1800     RETVAL = attachable::mortals.size ();
1801     OUTPUT: RETVAL
1802    
1803     #object *mortals (U32 index)
1804     # CODE:
1805     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1806     # OUTPUT: RETVAL
1807    
1808 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1809 root 1.115
1810 root 1.101 MODULE = cf PACKAGE = cf::global
1811    
1812     int invoke (SV *klass, int event, ...)
1813     CODE:
1814     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1815     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1816     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1817 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1818 root 1.101 OUTPUT: RETVAL
1819    
1820 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1821    
1822 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1823 root 1.62
1824 root 1.18 int invoke (object *op, int event, ...)
1825     CODE:
1826     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1827 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1828     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1829 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1830 root 1.18 OUTPUT: RETVAL
1831    
1832     SV *registry (object *op)
1833    
1834 root 1.134 int objects_size ()
1835     CODE:
1836     RETVAL = objects.size ();
1837     OUTPUT: RETVAL
1838    
1839     object *objects (U32 index)
1840     CODE:
1841     RETVAL = index < objects.size () ? objects [index] : 0;
1842     OUTPUT: RETVAL
1843    
1844     int actives_size ()
1845     CODE:
1846     RETVAL = actives.size ();
1847     OUTPUT: RETVAL
1848    
1849     object *actives (U32 index)
1850 root 1.57 CODE:
1851 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1852 root 1.57 OUTPUT: RETVAL
1853    
1854 root 1.215 const char *slot_use_name (U32 slot)
1855 root 1.205 ALIAS:
1856 root 1.215 slot_nonuse_name = 1
1857 root 1.205 CODE:
1858     {
1859     if (slot >= NUM_BODY_LOCATIONS)
1860     croak ("body slot index out of range");
1861    
1862     switch (ix)
1863     {
1864 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1865     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1866 root 1.205 }
1867     }
1868     OUTPUT:
1869     RETVAL
1870    
1871 root 1.1 # missing properties
1872    
1873 root 1.54 object *head (object *op)
1874     PROTOTYPE: $
1875     CODE:
1876 root 1.134 RETVAL = op->head_ ();
1877 root 1.54 OUTPUT: RETVAL
1878    
1879 root 1.1 void
1880     inv (object *obj)
1881     PROTOTYPE: $
1882     PPCODE:
1883     {
1884 root 1.254 for (object *o = obj->inv; o; o = o->below)
1885 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1886 root 1.1 }
1887    
1888 root 1.102 void
1889     set_animation (object *op, int idx)
1890     CODE:
1891     SET_ANIMATION (op, idx);
1892    
1893 elmex 1.160 int
1894     num_animations (object *op)
1895     CODE:
1896     RETVAL = NUM_ANIMATIONS (op);
1897     OUTPUT: RETVAL
1898    
1899 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1900     ALIAS:
1901     slot_used = 1
1902     CODE:
1903     {
1904     if (slot >= NUM_BODY_LOCATIONS)
1905     croak ("body slot index out of range");
1906    
1907 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1908 root 1.205
1909     if (items > 2)
1910     if (ix)
1911 root 1.208 op->slot[slot].used = value;
1912     else
1913 root 1.205 op->slot[slot].info = value;
1914     }
1915     OUTPUT:
1916     RETVAL
1917    
1918 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1919 root 1.58
1920     object *find_marked_object (object *op)
1921    
1922 root 1.109 int need_identify (object *obj);
1923 root 1.1
1924     int apply_shop_mat (object *shop_mat, object *op);
1925    
1926 root 1.27 int move (object *op, int dir, object *originator = op)
1927     CODE:
1928     RETVAL = move_ob (op, dir, originator);
1929     OUTPUT:
1930     RETVAL
1931 root 1.1
1932 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1933     CODE:
1934     manual_apply (applied, applier, flags);
1935 root 1.1
1936 root 1.74 void apply_below (object *op)
1937     CODE:
1938     player_apply_below (op);
1939 root 1.1
1940 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1941    
1942 root 1.116 #//TODO
1943     object *clone_ (object *op, int recursive = 0)
1944 root 1.74 CODE:
1945     if (recursive)
1946     RETVAL = object_create_clone (op);
1947     else
1948     {
1949     RETVAL = object::create ();
1950 root 1.75 op->copy_to (RETVAL);
1951 root 1.74 }
1952     OUTPUT: RETVAL
1953 root 1.1
1954 root 1.74 int pay_item (object *op, object *buyer)
1955     CODE:
1956     RETVAL = pay_for_item (op, buyer);
1957     OUTPUT: RETVAL
1958 root 1.1
1959 root 1.74 int pay_amount (object *op, uint64 amount)
1960     CODE:
1961     RETVAL = pay_for_amount (amount, op);
1962     OUTPUT: RETVAL
1963 root 1.1
1964     void pay_player (object *op, uint64 amount)
1965    
1966 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1967 root 1.1
1968 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1969 root 1.1
1970 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1971     CODE:
1972     do_learn_spell (op, sp, special_prayer);
1973 root 1.1
1974 root 1.74 void forget_spell (object *op, object *sp)
1975     CODE:
1976     do_forget_spell (op, query_name (sp));
1977 root 1.1
1978 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1979 root 1.74 CODE:
1980     RETVAL = check_spell_known (op, spellname);
1981     OUTPUT: RETVAL
1982 root 1.1
1983 root 1.74 int query_money (object *op)
1984 root 1.1 ALIAS: money = 0
1985    
1986 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1987 root 1.1 ALIAS: cost = 0
1988    
1989 root 1.74 void spring_trap (object *op, object *victim)
1990 root 1.1
1991 root 1.74 int check_trigger (object *op, object *cause)
1992 root 1.1
1993 root 1.74 void drop (object *who, object *op)
1994 root 1.1
1995 root 1.74 void pick_up (object *who, object *op)
1996 root 1.1
1997 root 1.102 void update_object (object *op, int action)
1998 root 1.1
1999 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2000 root 1.1
2001     void player_lvl_adj (object *who, object *skill = 0)
2002    
2003     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2004    
2005     int calc_skill_exp (object *who, object *op, object *skill);
2006    
2007     void push_button (object *op);
2008    
2009     void use_trigger (object *op);
2010    
2011 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2012 root 1.1
2013     void remove_button_link (object *op);
2014    
2015 elmex 1.232 void handle_apply_yield (object *op);
2016    
2017 root 1.1
2018     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2019    
2020     # no clean way to get an object from an archetype - stupid idiotic
2021     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2022    
2023 root 1.183 object *new (utf8_string archetype = 0)
2024 root 1.1 PROTOTYPE: ;$
2025     CODE:
2026 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2027 root 1.1 OUTPUT:
2028     RETVAL
2029    
2030 root 1.225 object *find_object (U32 tag)
2031    
2032 root 1.218 # TODO: nuke
2033 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2034 root 1.1 PROTOTYPE: $$$$$$
2035     CODE:
2036     {
2037 root 1.257 RETVAL = insert_ob_in_map_at (ob, where, orig, flag, x, y);
2038 root 1.1 }
2039    
2040 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
2041 root 1.1
2042 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
2043 root 1.1
2044     object *get_nearest_player (object *ob)
2045     ALIAS: nearest_player = 0
2046     PREINIT:
2047     extern object *get_nearest_player (object *);
2048    
2049     void rangevector (object *ob, object *other, int flags = 0)
2050     PROTOTYPE: $$;$
2051     PPCODE:
2052     {
2053     rv_vector rv;
2054     get_rangevector (ob, other, &rv, flags);
2055     EXTEND (SP, 5);
2056     PUSHs (newSVuv (rv.distance));
2057     PUSHs (newSViv (rv.distance_x));
2058     PUSHs (newSViv (rv.distance_y));
2059     PUSHs (newSViv (rv.direction));
2060 root 1.257 PUSHs (to_sv (rv.part));
2061 root 1.1 }
2062    
2063     bool on_same_map_as (object *ob, object *other)
2064     CODE:
2065     RETVAL = on_same_map (ob, other);
2066     OUTPUT: RETVAL
2067    
2068 root 1.183 const_utf8_string
2069 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2070 root 1.1 CODE:
2071 root 1.58 RETVAL = query_base_name (op, plural);
2072 root 1.1 OUTPUT: RETVAL
2073    
2074 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
2075    
2076 root 1.256 # return the tail of an object, excluding itself
2077     void
2078     tail (object *op)
2079     PPCODE:
2080     while ((op = op->more))
2081     XPUSHs (sv_2mortal (to_sv (op)));
2082    
2083 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2084    
2085     player *player (object *op)
2086     CODE:
2087     RETVAL = op->contr;
2088     OUTPUT: RETVAL
2089    
2090 root 1.257 bool move_player (object *op, int dir)
2091    
2092 root 1.105 void check_score (object *op)
2093    
2094 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2095 root 1.120 CODE:
2096     new_draw_info (flags, 0, op, txt);
2097 root 1.1
2098     void kill_player (object *op)
2099    
2100 root 1.257 void esrv_send_item (object *pl, object *item)
2101    
2102     void esrv_update_item (object *pl, int what, object *item)
2103     C_ARGS: what, pl, item
2104    
2105     void esrv_del_item (object *pl, int tag)
2106     C_ARGS: pl->contr, tag
2107 root 1.58
2108 root 1.183 int command_summon (object *op, utf8_string params)
2109 root 1.67
2110 root 1.183 int command_arrest (object *op, utf8_string params)
2111 root 1.67
2112 root 1.66
2113 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2114 root 1.1
2115 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2116 root 1.62
2117 root 1.18 int invoke (player *pl, int event, ...)
2118     CODE:
2119     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2120 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2121     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2122 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2123 root 1.18 OUTPUT: RETVAL
2124    
2125 root 1.12 SV *registry (player *pl)
2126 root 1.1
2127 root 1.102 void
2128     save_stats (player *pl)
2129     CODE:
2130     pl->ob->stats.hp = pl->ob->stats.maxhp;
2131     pl->ob->stats.sp = pl->ob->stats.maxsp;
2132     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2133     pl->orig_stats = pl->ob->stats;
2134    
2135 root 1.217 void clear_los (player *pl)
2136    
2137 root 1.1 bool
2138     cell_visible (player *pl, int dx, int dy)
2139     CODE:
2140 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2141     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2142 root 1.1 OUTPUT:
2143     RETVAL
2144    
2145 root 1.4 void
2146 root 1.1 send (player *pl, SV *packet)
2147     CODE:
2148     {
2149     STRLEN len;
2150     char *buf = SvPVbyte (packet, len);
2151    
2152 root 1.258 if (len > MAXSOCKBUF)
2153     pl->failmsg ("[packet too long for client]");
2154     else if (pl->ns)
2155 root 1.100 pl->ns->send_packet (buf, len);
2156 root 1.1 }
2157    
2158     int
2159     listening (player *pl, int new_value = -1)
2160     CODE:
2161     RETVAL = pl->listening;
2162     if (new_value >= 0)
2163     pl->listening = new_value;
2164     OUTPUT:
2165     RETVAL
2166    
2167 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2168 root 1.45 PROTOTYPE: $;$$$
2169 root 1.1 PPCODE:
2170 root 1.45 if (GIMME_V != G_VOID)
2171     {
2172     EXTEND (SP, 3);
2173     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2174     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2175     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2176     }
2177 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2178     if (x) sv_to (x, pl->bed_x);
2179     if (y) sv_to (y, pl->bed_y);
2180 root 1.1
2181     void
2182     list ()
2183     PPCODE:
2184 root 1.128 for_all_players (pl)
2185 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2186 root 1.1
2187    
2188     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2189    
2190 root 1.61 int invoke (maptile *map, int event, ...)
2191 root 1.18 CODE:
2192     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2193 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2194     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2195 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2196 root 1.25 OUTPUT: RETVAL
2197 root 1.18
2198 root 1.61 SV *registry (maptile *map)
2199 root 1.12
2200 root 1.255 void
2201     find_tagged_objects (maptile *map, utf8_string tag = 0)
2202     PPCODE:
2203     {
2204     if (!map->spaces)
2205     XSRETURN_EMPTY;
2206    
2207     if (tag)
2208     {
2209     shstr_cmp tag_ (tag);
2210    
2211     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2212     for (object *op = ms->bot; op; op = op->above)
2213     if (op->tag == tag_)
2214     XPUSHs (sv_2mortal (to_sv (op)));
2215     }
2216     else
2217     {
2218     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2219     for (object *op = ms->bot; op; op = op->above)
2220     if (op->tag)
2221     XPUSHs (sv_2mortal (to_sv (op)));
2222     }
2223     }
2224    
2225 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2226 root 1.1
2227 root 1.116 void
2228     maptile::instantiate ()
2229    
2230     maptile *new ()
2231 root 1.1 PROTOTYPE:
2232     CODE:
2233 root 1.116 RETVAL = new maptile;
2234 root 1.1 OUTPUT:
2235     RETVAL
2236    
2237 root 1.116 void
2238 root 1.117 maptile::players ()
2239     PPCODE:
2240     if (GIMME_V == G_SCALAR)
2241 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2242 root 1.117 else if (GIMME_V == G_ARRAY)
2243     {
2244     EXTEND (SP, THIS->players);
2245     for_all_players (pl)
2246     if (pl->ob && pl->ob->map == THIS)
2247 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2248 root 1.117 }
2249    
2250 root 1.156 void
2251 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2252 root 1.156 CODE:
2253     {
2254 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2255     croak ("maptile::add_underlay: palette must be arrayref");
2256 root 1.156
2257 root 1.168 palette = SvRV (palette);
2258 root 1.156
2259 root 1.168 STRLEN idxlen;
2260     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2261 root 1.156
2262 root 1.168 for (int x = 0; x < THIS->width; ++x)
2263     for (int y = 0; y < THIS->height; ++y)
2264     {
2265     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2266     if (op->flag [FLAG_IS_FLOOR])
2267     goto skip_space;
2268    
2269     {
2270     int offs = offset + y * stride + x;
2271     if (IN_RANGE_EXC (offs, 0, idxlen))
2272     {
2273     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2274     {
2275     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2276     ob->flag [FLAG_NO_MAP_SAVE] = true;
2277     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2278 root 1.200
2279     if (ob->randomitems)
2280     {
2281 root 1.203 if (!ob->above)
2282     {
2283     ob->create_treasure (ob->randomitems);
2284    
2285     for (object *op = ob->above; op; op = op->above)
2286     op->flag [FLAG_NO_MAP_SAVE] = true;
2287     }
2288    
2289 root 1.200 ob->randomitems = 0;
2290     }
2291 root 1.168 }
2292     }
2293     }
2294 root 1.156
2295 root 1.168 skip_space: ;
2296     }
2297     }
2298    
2299     void
2300     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2301     CODE:
2302     {
2303     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2304     croak ("maptile::set_regiondata: palette must be arrayref");
2305    
2306     palette = SvRV (palette);
2307    
2308     STRLEN idxlen;
2309     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2310    
2311 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2312 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2313    
2314     for (int i = av_len ((AV *)palette) + 1; i--; )
2315 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2316 root 1.168
2317     for (int y = 0; y < THIS->height; ++y)
2318     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2319    
2320     sfree (THIS->regions, THIS->size ());
2321 root 1.230 delete [] THIS->regionmap;
2322 root 1.168
2323     THIS->regions = regions;
2324 root 1.156 THIS->regionmap = regionmap;
2325     }
2326    
2327 root 1.193 void
2328     maptile::create_region_treasure ()
2329     CODE:
2330     {
2331     object *op = object::create ();
2332     op->type = FLOOR;
2333     op->map = THIS;
2334    
2335     for (int x = 0; x < THIS->width; ++x)
2336     for (int y = 0; y < THIS->height; ++y)
2337     {
2338     region *rgn = THIS->region (x, y);
2339    
2340     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2341     if (rgn->treasure && rndm () < rgn->treasure_density)
2342     {
2343     op->x = x;
2344     op->y = y;
2345     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2346     }
2347     }
2348    
2349     op->destroy ();
2350     }
2351    
2352 root 1.74 int out_of_map (maptile *map, int x, int y)
2353    
2354 root 1.29 void
2355 root 1.61 trigger (maptile *map, long connection, bool state = true)
2356 root 1.29 CODE:
2357     activate_connection (map, connection, state);
2358    
2359     void
2360 root 1.61 get_connection (maptile *map, long connection)
2361 root 1.29 PPCODE:
2362     oblinkpt *obp = get_connection_links (map, connection);
2363     if (obp)
2364     for (objectlink *ol = obp->link; ol; ol = ol->next)
2365 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2366 root 1.1
2367     void
2368 root 1.140 get_map_flags (maptile *map, int x, int y)
2369 root 1.1 PPCODE:
2370     {
2371 root 1.61 maptile *nmap = 0;
2372 root 1.1 I16 nx = 0, ny = 0;
2373 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2374 root 1.1
2375     EXTEND (SP, 4);
2376     PUSHs (sv_2mortal (newSViv (flags)));
2377    
2378     if (GIMME_V == G_ARRAY)
2379     {
2380 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2381 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2382     PUSHs (sv_2mortal (newSViv (ny)));
2383     }
2384     }
2385    
2386     void
2387 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2388 root 1.1 PROTOTYPE: $$$
2389     PPCODE:
2390     {
2391     object *o;
2392 root 1.61 maptile *nmap = 0;
2393 root 1.1 I16 nx, ny;
2394    
2395 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2396 root 1.1
2397     if (nmap)
2398     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2399 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2400 root 1.1 }
2401    
2402     SV *
2403 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2404 root 1.1 PROTOTYPE: $$$
2405     ALIAS:
2406     top_at = 1
2407     flags_at = 2
2408     light_at = 3
2409     move_block_at = 4
2410     move_slow_at = 5
2411     move_on_at = 6
2412     move_off_at = 7
2413     INIT:
2414 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2415 root 1.1 CODE:
2416     switch (ix)
2417     {
2418 root 1.257 case 0: RETVAL = to_sv (GET_MAP_OB (obj, x, y)); break;
2419     case 1: RETVAL = to_sv (GET_MAP_TOP (obj, x, y)); break;
2420     case 2: RETVAL = newSVuv (GET_MAP_FLAGS (obj, x, y)); break;
2421     case 3: RETVAL = newSViv (GET_MAP_LIGHT (obj, x, y)); break;
2422     case 4: RETVAL = newSVuv (GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2423     case 5: RETVAL = newSVuv (GET_MAP_MOVE_SLOW (obj, x, y)); break;
2424     case 6: RETVAL = newSVuv (GET_MAP_MOVE_ON (obj, x, y)); break;
2425     case 7: RETVAL = newSVuv (GET_MAP_MOVE_OFF (obj, x, y)); break;
2426 root 1.1 }
2427 root 1.122 OUTPUT: RETVAL
2428 root 1.1
2429 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2430    
2431     void fix_walls_around (maptile *map, int x, int y)
2432 root 1.1
2433 root 1.117 # worst xs function of my life
2434 root 1.140 bool
2435 root 1.117 _create_random_map (\
2436 root 1.140 maptile *self,\
2437 root 1.183 utf8_string wallstyle,\
2438     utf8_string wall_name,\
2439     utf8_string floorstyle,\
2440     utf8_string monsterstyle,\
2441     utf8_string treasurestyle,\
2442     utf8_string layoutstyle,\
2443     utf8_string doorstyle,\
2444     utf8_string decorstyle,\
2445     utf8_string origin_map,\
2446     utf8_string final_map,\
2447     utf8_string exitstyle,\
2448     utf8_string this_map,\
2449     utf8_string exit_on_final_map,\
2450 root 1.146 int xsize,\
2451     int ysize,\
2452 root 1.117 int expand2x,\
2453     int layoutoptions1,\
2454     int layoutoptions2,\
2455     int layoutoptions3,\
2456     int symmetry,\
2457     int difficulty,\
2458     int difficulty_given,\
2459     float difficulty_increase,\
2460     int dungeon_level,\
2461     int dungeon_depth,\
2462     int decoroptions,\
2463     int orientation,\
2464     int origin_y,\
2465     int origin_x,\
2466 root 1.146 U32 random_seed,\
2467 root 1.117 val64 total_map_hp,\
2468     int map_layout_style,\
2469     int treasureoptions,\
2470     int symmetry_used,\
2471 root 1.137 region *region,\
2472 root 1.183 utf8_string custom\
2473 root 1.117 )
2474     CODE:
2475     {
2476     random_map_params rmp;
2477    
2478     assign (rmp.wallstyle , wallstyle);
2479     assign (rmp.wall_name , wall_name);
2480     assign (rmp.floorstyle , floorstyle);
2481     assign (rmp.monsterstyle , monsterstyle);
2482     assign (rmp.treasurestyle , treasurestyle);
2483     assign (rmp.layoutstyle , layoutstyle);
2484     assign (rmp.doorstyle , doorstyle);
2485     assign (rmp.decorstyle , decorstyle);
2486     assign (rmp.exitstyle , exitstyle);
2487     assign (rmp.exit_on_final_map, exit_on_final_map);
2488    
2489 root 1.122 rmp.origin_map = origin_map;
2490     rmp.final_map = final_map;
2491     rmp.this_map = this_map;
2492 root 1.146 rmp.xsize = xsize;
2493     rmp.ysize = ysize;
2494 root 1.117 rmp.expand2x = expand2x;
2495     rmp.layoutoptions1 = layoutoptions1;
2496     rmp.layoutoptions2 = layoutoptions2;
2497     rmp.layoutoptions3 = layoutoptions3;
2498     rmp.symmetry = symmetry;
2499     rmp.difficulty = difficulty;
2500     rmp.difficulty_given = difficulty_given;
2501     rmp.difficulty_increase = difficulty_increase;
2502     rmp.dungeon_level = dungeon_level;
2503     rmp.dungeon_depth = dungeon_depth;
2504     rmp.decoroptions = decoroptions;
2505     rmp.orientation = orientation;
2506     rmp.origin_y = origin_y;
2507     rmp.origin_x = origin_x;
2508     rmp.random_seed = random_seed;
2509 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2510 root 1.117 rmp.map_layout_style = map_layout_style;
2511     rmp.treasureoptions = treasureoptions;
2512     rmp.symmetry_used = symmetry_used;
2513     rmp.region = region;
2514 root 1.137 rmp.custom = custom;
2515 root 1.117
2516 root 1.140 RETVAL = self->generate_random_map (&rmp);
2517 root 1.117 }
2518     OUTPUT:
2519     RETVAL
2520    
2521 root 1.19 MODULE = cf PACKAGE = cf::arch
2522 root 1.1
2523 root 1.218 int archetypes_size ()
2524     CODE:
2525     RETVAL = archetypes.size ();
2526     OUTPUT: RETVAL
2527    
2528     archetype *archetypes (U32 index)
2529     CODE:
2530     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2531     OUTPUT: RETVAL
2532 root 1.1
2533 root 1.212 object *instantiate (archetype *arch)
2534     CODE:
2535     RETVAL = arch_to_object (arch);
2536     OUTPUT:
2537     RETVAL
2538    
2539 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2540 root 1.1
2541 root 1.19 MODULE = cf PACKAGE = cf::party
2542 root 1.1
2543 root 1.19 partylist *first ()
2544 root 1.1 PROTOTYPE:
2545 root 1.19 CODE:
2546     RETVAL = get_firstparty ();
2547     OUTPUT: RETVAL
2548 root 1.1
2549 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2550 root 1.1
2551 root 1.19 MODULE = cf PACKAGE = cf::region
2552 root 1.1
2553 root 1.161 void
2554     list ()
2555     PPCODE:
2556     for_all_regions (rgn)
2557     XPUSHs (sv_2mortal (to_sv (rgn)));
2558    
2559 root 1.183 region *find (utf8_string name)
2560 root 1.161 PROTOTYPE: $
2561 root 1.19 CODE:
2562 root 1.161 RETVAL = region::find (name);
2563 root 1.19 OUTPUT: RETVAL
2564 root 1.1
2565 root 1.183 region *find_fuzzy (utf8_string name)
2566 root 1.122 PROTOTYPE: $
2567     CODE:
2568 root 1.161 RETVAL = region::find_fuzzy (name);
2569 root 1.122 OUTPUT: RETVAL
2570    
2571 root 1.186 int specificity (region *rgn)
2572     CODE:
2573     RETVAL = 0;
2574     while (rgn = rgn->parent)
2575     RETVAL++;
2576     OUTPUT: RETVAL
2577    
2578 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2579 root 1.1
2580 root 1.19 MODULE = cf PACKAGE = cf::living
2581 root 1.1
2582 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2583 root 1.1
2584 root 1.76 MODULE = cf PACKAGE = cf::settings
2585    
2586 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2587 root 1.76
2588 root 1.84 MODULE = cf PACKAGE = cf::client
2589 root 1.79
2590 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2591 root 1.79
2592 root 1.84 int invoke (client *ns, int event, ...)
2593 root 1.79 CODE:
2594 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2595 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2596     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2597 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2598 root 1.79 OUTPUT: RETVAL
2599    
2600 root 1.84 SV *registry (client *ns)
2601 root 1.79
2602 root 1.100 void
2603     list ()
2604     PPCODE:
2605     EXTEND (SP, clients.size ());
2606     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2607     PUSHs (sv_2mortal (to_sv (*i)));
2608    
2609 root 1.88 void
2610 root 1.100 client::send_packet (SV *packet)
2611     CODE:
2612     {
2613     STRLEN len;
2614     char *buf = SvPVbyte (packet, len);
2615    
2616 root 1.258 if (len > MAXSOCKBUF)
2617     {
2618     // ugly
2619     if (THIS->pl)
2620     THIS->pl->failmsg ("[packet too long for client]");
2621     }
2622     else
2623     THIS->send_packet (buf, len);
2624 root 1.100 }
2625    
2626 root 1.237 faceidx
2627 root 1.238 client::need_face (utf8_string name, int pri = 0)
2628 root 1.237 CODE:
2629 root 1.238 RETVAL = face_find (name, 0);
2630     if (RETVAL)
2631     {
2632     THIS->send_face (RETVAL, pri);
2633     THIS->flush_fx ();
2634     }
2635     OUTPUT:
2636     RETVAL
2637    
2638     int
2639     client::fx_want (int idx, int value = -1)
2640     CODE:
2641     if (0 < idx && idx < FT_NUM)
2642     {
2643     RETVAL = THIS->fx_want [idx];
2644     if (items > 2)
2645     THIS->fx_want [idx] = value;
2646     }
2647     else
2648     RETVAL = 0;
2649 root 1.237 OUTPUT:
2650     RETVAL
2651    
2652 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2653    
2654     faceidx sound_find (utf8_string name)
2655    
2656 root 1.240 void sound_set (utf8_string str, faceidx face)
2657    
2658     # dire hack
2659     void old_sound_index (int idx, faceidx face)
2660     CODE:
2661     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2662     old_sound_index [idx] = face;
2663    
2664 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2665    
2666 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2667 root 1.176
2668 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2669 root 1.176
2670 root 1.183 faceidx alloc (utf8_string name)
2671 root 1.176 CODE:
2672     {
2673     do
2674     {
2675     RETVAL = faces.size ();
2676 root 1.177 faces.resize (RETVAL + 1);
2677 root 1.176 }
2678     while (!RETVAL); // crude way to leave index 0
2679    
2680     faces [RETVAL].name = name;
2681     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2682    
2683     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2684     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2685     }
2686     OUTPUT: RETVAL
2687    
2688 root 1.227 void set_type (faceidx idx, int value)
2689     ALIAS:
2690     set_type = 0
2691     set_visibility = 1
2692     set_magicmap = 2
2693     set_smooth = 3
2694     set_smoothlevel = 4
2695 root 1.176 CODE:
2696 root 1.229 faceinfo *f = face_info (idx); assert (f);
2697 root 1.227 switch (ix)
2698     {
2699     case 0: f->type = value; break;
2700     case 1: f->visibility = value; break;
2701     case 2: f->magicmap = value; break;
2702     case 3: f->smooth = value; break;
2703     case 4: f->smoothlevel = value; break;
2704     }
2705 root 1.177
2706     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2707 root 1.176 CODE:
2708 root 1.182 {
2709 root 1.231 faceinfo *f = face_info (idx); assert (f);
2710     facedata *d = &(faceset ? f->data64 : f->data32);
2711 root 1.181 sv_to (data, d->data);
2712     STRLEN clen;
2713     char *cdata = SvPVbyte (chksum, clen);
2714 root 1.182 clen = min (CHKSUM_SIZE, clen);
2715    
2716     if (memcmp (d->chksum, cdata, clen))
2717     {
2718     memcpy (d->chksum, cdata, clen);
2719    
2720     // invalidate existing client face info
2721     for_all_clients (ns)
2722     if (ns->faceset == faceset)
2723     {
2724     ns->faces_sent [idx] = false;
2725     ns->force_newmap = true;
2726     }
2727     }
2728     }
2729 root 1.176
2730 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2731     CODE:
2732 root 1.267 facedata *d = face_data (idx, faceset);
2733     if (!d) XSRETURN_UNDEF;
2734 root 1.229 RETVAL = d->data.size ();
2735     OUTPUT:
2736     RETVAL
2737    
2738     SV *get_chksum (faceidx idx, int faceset = 0)
2739     CODE:
2740 root 1.267 facedata *d = face_data (idx, faceset);
2741     if (!d) XSRETURN_UNDEF;
2742 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2743     OUTPUT:
2744     RETVAL
2745    
2746 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2747     CODE:
2748     facedata *d = face_data (idx, faceset);
2749     if (!d) XSRETURN_UNDEF;
2750     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2751     OUTPUT:
2752     RETVAL
2753    
2754 root 1.177 void invalidate (faceidx idx)
2755     CODE:
2756     for_all_clients (ns)
2757 root 1.182 {
2758     ns->faces_sent [idx] = false;
2759     ns->force_newmap = true;
2760     }
2761 root 1.177
2762     void invalidate_all ()
2763     CODE:
2764     for_all_clients (ns)
2765 root 1.182 {
2766     ns->faces_sent.reset ();
2767     ns->force_newmap = true;
2768     }
2769 root 1.177
2770 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2771    
2772     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2773    
2774     animidx anim_find (utf8_string name)
2775     CODE:
2776     RETVAL = animation::find (name).number;
2777     OUTPUT: RETVAL
2778    
2779     animidx set (utf8_string name, SV *frames, int facings = 1)
2780     CODE:
2781     {
2782     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2783     croak ("frames must be an arrayref");
2784    
2785     AV *av = (AV *)SvRV (frames);
2786    
2787     animation *anim = &animation::find (name);
2788     if (anim->number)
2789     {
2790     anim->resize (av_len (av) + 1);
2791     anim->facings = facings;
2792     }
2793     else
2794     anim = &animation::create (name, av_len (av) + 1, facings);
2795    
2796     for (int i = 0; i < anim->num_animations; ++i)
2797     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2798     }
2799     OUTPUT: RETVAL
2800    
2801     void invalidate_all ()
2802     CODE:
2803     for_all_clients (ns)
2804     ns->anims_sent.reset ();
2805    
2806 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2807    
2808     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2809    
2810     SV *
2811     new (char *klass)
2812     CODE:
2813     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2814     OUTPUT: RETVAL
2815    
2816     void
2817     DESTROY (SV *sv)
2818     CODE:
2819     object_freezer *self;
2820     sv_to (sv, self);
2821     delete self;
2822    
2823     MODULE = cf PACKAGE = cf::object::thawer
2824    
2825     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2826    
2827     SV *
2828     new_from_file (char *klass, octet_string path)
2829     CODE:
2830     object_thawer *f = new object_thawer (path);
2831     if (!*f)
2832     {
2833     delete f;
2834     XSRETURN_UNDEF;
2835     }
2836     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2837     OUTPUT: RETVAL
2838    
2839     void
2840     DESTROY (SV *sv)
2841     CODE:
2842     object_thawer *self;
2843     sv_to (sv, self);
2844     delete self;
2845    
2846 root 1.252 void
2847 root 1.253 extract_tags (object_thawer *self)
2848 root 1.254 PPCODE:
2849 root 1.252 while (self->kw != KW_EOF)
2850     {
2851 root 1.254 PUTBACK;
2852 root 1.272 coroapi::cede_to_tick ();
2853 root 1.254 SPAGAIN;
2854 root 1.253
2855 root 1.252 if (self->kw == KW_tag)
2856 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
2857 root 1.252
2858     self->skip ();
2859     }
2860