ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.281
Committed: Tue Apr 22 07:01:47 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.280: +1 -2 lines
Log Message:
see Changes

File Contents

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