ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.287
Committed: Sun May 4 15:22:14 2008 UTC (16 years ago) by root
Branch: MAIN
CVS Tags: rel-2_53
Changes since 1.286: +15 -0 lines
Log Message:
fix the dummy-teleport-objects c callers

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 root 1.286 player *retval = 0;
983     if (count) sv_to (POPs, retval);
984 root 1.244
985 root 1.286 CALL_END;
986    
987     return retval;
988     }
989    
990     maptile *
991     find_style (const char *dirname, const char *stylename, int difficulty)
992     {
993     CALL_BEGIN (3);
994     CALL_ARG (dirname);
995     CALL_ARG (stylename);
996     CALL_ARG (difficulty);
997     CALL_CALL ("ext::map_random::find_style", G_SCALAR);
998    
999     maptile *retval = 0;
1000     if (count) sv_to (POPs, retval);
1001 root 1.244
1002     CALL_END;
1003    
1004     return retval;
1005     }
1006    
1007 root 1.116 maptile *
1008 root 1.126 maptile::find_sync (const char *path, maptile *origin)
1009 root 1.116 {
1010     CALL_BEGIN (2);
1011     CALL_ARG (path);
1012     CALL_ARG (origin);
1013 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
1014 root 1.116
1015 root 1.286 maptile *retval = 0;
1016     if (count) sv_to (POPs, retval);
1017 root 1.116
1018     CALL_END;
1019    
1020     return retval;
1021     }
1022    
1023 root 1.135 maptile *
1024 root 1.243 maptile::find_async (const char *path, maptile *origin, bool load)
1025 root 1.135 {
1026 root 1.243 CALL_BEGIN (3);
1027 root 1.135 CALL_ARG (path);
1028     CALL_ARG (origin);
1029 root 1.243 CALL_ARG (load);
1030 root 1.135 CALL_CALL ("cf::map::find_async", G_SCALAR);
1031    
1032 root 1.286 maptile *retval = 0;
1033     if (count) sv_to (POPs, retval);
1034 root 1.135
1035     CALL_END;
1036    
1037     return retval;
1038     }
1039    
1040 root 1.116 void
1041 root 1.126 maptile::do_load_sync ()
1042     {
1043     CALL_BEGIN (1);
1044     CALL_ARG (this);
1045     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
1046     CALL_END;
1047     }
1048    
1049     void
1050 root 1.116 maptile::change_all_map_light (int change)
1051     {
1052     CALL_BEGIN (1);
1053     CALL_ARG (change);
1054     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
1055     CALL_END;
1056     }
1057    
1058     void
1059     object::enter_exit (object *exit)
1060     {
1061     if (type != PLAYER)
1062     return;
1063    
1064     CALL_BEGIN (2);
1065     CALL_ARG (this);
1066     CALL_ARG (exit);
1067     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
1068     CALL_END;
1069     }
1070    
1071 root 1.287 void
1072     object::player_goto (const char *path, int x, int y)
1073     {
1074     if (type != PLAYER)
1075     return;
1076    
1077     CALL_BEGIN (4);
1078     CALL_ARG (this);
1079     CALL_ARG (path);
1080     CALL_ARG (x);
1081     CALL_ARG (y);
1082     CALL_CALL ("cf::object::player::goto", G_VOID);
1083     CALL_END;
1084     }
1085    
1086 root 1.247 const char *
1087     object::ref () const
1088     {
1089     if (type == PLAYER)
1090     return format ("player/<1.%llx>/%s", (unsigned long long)uuid.seq, &name);
1091     else
1092     return 0;
1093     }
1094    
1095     object *
1096     object::deref (const char *ref)
1097     {
1098 root 1.249 object *retval = 0;
1099 root 1.247
1100 root 1.249 if (ref)
1101     {
1102     CALL_BEGIN (1);
1103     CALL_ARG (ref);
1104     CALL_CALL ("cf::object::deref", G_SCALAR);
1105    
1106     if (count)
1107     sv_to (POPs, retval);
1108 root 1.247
1109 root 1.249 CALL_END;
1110     }
1111 root 1.247
1112     return retval;
1113     }
1114    
1115 root 1.198 void
1116     log_backtrace (const char *msg)
1117     {
1118     #if HAVE_BACKTRACE
1119     void *addr [20];
1120     int size = backtrace (addr, 20);
1121    
1122     CALL_BEGIN (size);
1123     CALL_ARG (msg);
1124     for (int i = 0; i < size; ++i)
1125     CALL_ARG ((IV)addr [i]);
1126     CALL_CALL ("cf::_log_backtrace", G_VOID);
1127     CALL_END;
1128     #endif
1129     }
1130    
1131 root 1.116 /////////////////////////////////////////////////////////////////////////////
1132    
1133 root 1.265 struct EVAPI *evapi::GEVAPI;
1134     struct CoroAPI *coroapi::GCoroAPI;
1135 root 1.80
1136 root 1.189 void coroapi::do_cede_to_tick ()
1137     {
1138 root 1.272 cede_pending = 0;
1139 root 1.189 cede ();
1140     }
1141 root 1.124
1142 root 1.188 void
1143     coroapi::wait_for_tick ()
1144     {
1145     CALL_BEGIN (0);
1146     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1147     CALL_END;
1148     }
1149    
1150     void
1151     coroapi::wait_for_tick_begin ()
1152     {
1153     CALL_BEGIN (0);
1154     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1155     CALL_END;
1156     }
1157    
1158 root 1.85 void
1159 root 1.80 iow::poll (int events)
1160     {
1161 root 1.265 if (events != this->events)
1162 root 1.81 {
1163 root 1.265 int active = ev_is_active ((ev_io *)this);
1164     if (active) stop ();
1165     ev_io_set ((ev_io *)this, fd, events);
1166     if (active) start ();
1167 root 1.81 }
1168 root 1.80 }
1169    
1170 root 1.109 void
1171     _connect_to_perl ()
1172     {
1173 root 1.272 stash_cf = gv_stashpv ("cf", 1);
1174 root 1.109
1175     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1176     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1177     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1178     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1179     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1180     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1181     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1182     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1183     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1184    
1185 root 1.272 sv_now = get_sv ("cf::NOW" , 1); SvUPGRADE (sv_now , SVt_NV);
1186     sv_runtime = get_sv ("cf::RUNTIME" , 1); SvUPGRADE (sv_runtime , SVt_NV);
1187     sv_tick_start = get_sv ("cf::TICK_START", 1); SvUPGRADE (sv_tick_start, SVt_NV);
1188     sv_next_tick = get_sv ("cf::NEXT_TICK" , 1); SvUPGRADE (sv_next_tick , SVt_NV);
1189 root 1.116
1190 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1191     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1192     cb_object = get_av ("cf::CB_OBJECT", 1);
1193     cb_player = get_av ("cf::CB_PLAYER", 1);
1194     cb_client = get_av ("cf::CB_CLIENT", 1);
1195     cb_type = get_av ("cf::CB_TYPE" , 1);
1196     cb_map = get_av ("cf::CB_MAP" , 1);
1197     }
1198    
1199 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1200    
1201     BOOT:
1202     {
1203 root 1.265 I_EV_API (PACKAGE); evapi::GEVAPI = GEVAPI;
1204     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1205 root 1.80
1206 root 1.189 _connect_to_perl ();
1207    
1208 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1209 root 1.63
1210 root 1.220 //{
1211     // require_pv ("Time::HiRes");
1212     //
1213     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1214     // if (!svp) croak ("Time::HiRes is required");
1215     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1216     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1217     //}
1218 root 1.189
1219 root 1.1 static const struct {
1220     const char *name;
1221     IV iv;
1222     } *civ, const_iv[] = {
1223     # define const_iv(name) { # name, (IV)name },
1224 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1225 root 1.198 const_iv (logBacktrace)
1226 root 1.180
1227 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1228    
1229     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1230 root 1.180
1231 root 1.5 const_iv (MAX_TIME)
1232 root 1.258 const_iv (MAXSOCKBUF)
1233 root 1.189
1234 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1235     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1236     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1237     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1238     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1239     const_iv (body_wrist) const_iv (body_waist)
1240 root 1.205
1241 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1242     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1243     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1244     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1245     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1246     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1247     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1248     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1249     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1250     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1251     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1252     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1253     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1254     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1255     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1256     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1257     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1258     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1259     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1260     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1261     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1262     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1263     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1264     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1265     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1266     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1267     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1268     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1269 root 1.1
1270 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1271 root 1.14
1272 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1273     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1274 root 1.1
1275 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1276     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1277     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1278     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1279     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1280     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1281     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1282    
1283     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1284     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1285 root 1.1 const_iv (WEAP_BLUD)
1286    
1287 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1288 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1289 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1290     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1291     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1292     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1293     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1294     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1295     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1296     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1297     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1298     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1299     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1300     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1301     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1302     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1303     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1304     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1305     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1306     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1307     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1308     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1309     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1310 root 1.245 const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1311 root 1.189 const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1312     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1313    
1314     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1315     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1316     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1317     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1318 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1319 root 1.250 const_iv (NDI_NOCREATE) const_iv (NDI_CLEAR)
1320 root 1.1
1321 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1322     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1323    
1324     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1325    
1326 root 1.212 const_iv (SP_RAISE_DEAD)
1327     const_iv (SP_RUNE)
1328     const_iv (SP_MAKE_MARK)
1329     const_iv (SP_BOLT)
1330     const_iv (SP_BULLET)
1331     const_iv (SP_EXPLOSION)
1332     const_iv (SP_CONE)
1333     const_iv (SP_BOMB)
1334     const_iv (SP_WONDER)
1335     const_iv (SP_SMITE)
1336     const_iv (SP_MAGIC_MISSILE)
1337     const_iv (SP_SUMMON_GOLEM)
1338     const_iv (SP_DIMENSION_DOOR)
1339     const_iv (SP_MAGIC_MAPPING)
1340     const_iv (SP_MAGIC_WALL)
1341     const_iv (SP_DESTRUCTION)
1342     const_iv (SP_PERCEIVE_SELF)
1343     const_iv (SP_WORD_OF_RECALL)
1344     const_iv (SP_INVISIBLE)
1345     const_iv (SP_PROBE)
1346     const_iv (SP_HEALING)
1347     const_iv (SP_CREATE_FOOD)
1348     const_iv (SP_EARTH_TO_DUST)
1349     const_iv (SP_CHANGE_ABILITY)
1350     const_iv (SP_BLESS)
1351     const_iv (SP_CURSE)
1352     const_iv (SP_SUMMON_MONSTER)
1353     const_iv (SP_CHARGING)
1354     const_iv (SP_POLYMORPH)
1355     const_iv (SP_ALCHEMY)
1356     const_iv (SP_REMOVE_CURSE)
1357     const_iv (SP_IDENTIFY)
1358     const_iv (SP_DETECTION)
1359     const_iv (SP_MOOD_CHANGE)
1360     const_iv (SP_MOVING_BALL)
1361     const_iv (SP_SWARM)
1362     const_iv (SP_CHANGE_MANA)
1363     const_iv (SP_DISPEL_RUNE)
1364     const_iv (SP_CREATE_MISSILE)
1365     const_iv (SP_CONSECRATE)
1366     const_iv (SP_ANIMATE_WEAPON)
1367     const_iv (SP_LIGHT)
1368     const_iv (SP_CHANGE_MAP_LIGHT)
1369     const_iv (SP_FAERY_FIRE)
1370     const_iv (SP_CAUSE_DISEASE)
1371     const_iv (SP_AURA)
1372     const_iv (SP_TOWN_PORTAL)
1373     const_iv (SP_PARTY_SPELL)
1374    
1375 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1376     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1377 root 1.1 const_iv (F_LOCKED)
1378    
1379 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1380    
1381     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1382     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1383    
1384     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1385    
1386     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1387 root 1.258 const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR)
1388 root 1.189
1389     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1390     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1391    
1392     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1393    
1394     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1395     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1396     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1397     const_iv (M_ICE) const_iv (M_SPECIAL)
1398    
1399     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1400     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1401    
1402     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1403     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1404     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1405     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1406     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1407     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1408     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1409     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1410     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1411     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1412 root 1.1 const_iv (SK_POISON_NAIL)
1413    
1414 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1415     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1416     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1417     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1418     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1419     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1420    
1421     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1422    
1423     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1424     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1425     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1426     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1427     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1428     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1429     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1430    
1431 root 1.276 const_iv (MAP_ACTIVE) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1432     const_iv (MAP_INACTIVE)
1433 root 1.189
1434     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1435     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1436    
1437 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1438    
1439 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1440    
1441     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1442 root 1.99
1443 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1444 root 1.117
1445     // random map generator
1446 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1447     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1448    
1449     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1450     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1451     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1452    
1453     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1454     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1455 root 1.195
1456     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1457 root 1.281 const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_MINIMAL)
1458 root 1.238
1459     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1460     const_iv (FT_RSRC) const_iv (FT_NUM)
1461 root 1.1 };
1462    
1463     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1464 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1465 root 1.1
1466     static const struct {
1467     const char *name;
1468 root 1.14 int skip;
1469 root 1.7 IV klass;
1470 root 1.1 IV iv;
1471 root 1.6 } *eiv, event_iv[] = {
1472 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1473 root 1.6 # include "eventinc.h"
1474     # undef def
1475     };
1476    
1477     AV *av = get_av ("cf::EVENT", 1);
1478    
1479     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1480 root 1.7 {
1481     AV *event = newAV ();
1482 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1483 root 1.7 av_push (event, newSViv (eiv->klass));
1484     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1485 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1486 root 1.7 }
1487 root 1.14 }
1488    
1489 root 1.109 void _connect_to_perl ()
1490 root 1.14
1491 root 1.210 void _recalc_want ()
1492    
1493 root 1.47 void _global_reattach ()
1494 root 1.14 CODE:
1495     {
1496     // reattach to all attachable objects in the game.
1497 root 1.128 for_all_clients (ns)
1498     ns->reattach ();
1499 root 1.96
1500 root 1.128 for_all_objects (op)
1501 root 1.109 op->reattach ();
1502 root 1.1 }
1503    
1504 root 1.192 # support function for map-world.ext
1505     void _quantise (SV *data_sv, SV *plt_sv)
1506     CODE:
1507     {
1508     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1509     croak ("_quantise called with invalid agruments");
1510    
1511     plt_sv = SvRV (plt_sv);
1512     SV **plt = AvARRAY (plt_sv);
1513     int plt_count = AvFILL (plt_sv) + 1;
1514    
1515     STRLEN len;
1516     char *data = SvPVbyte (data_sv, len);
1517     char *dst = data;
1518    
1519     while (len >= 3)
1520     {
1521     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1522     {
1523     char *val = SvPVX (*val_sv);
1524    
1525     if (val [0] == data [0]
1526     && val [1] == data [1]
1527     && val [2] == data [2])
1528     {
1529     *dst++ = val [3];
1530     goto next;
1531     }
1532     }
1533    
1534     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1535     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1536     dst - SvPVX (data_sv), len);
1537    
1538     next:
1539     data += 3;
1540     len -= 3;
1541     }
1542    
1543     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1544     }
1545    
1546 root 1.273 void evthread_start (int aiofd)
1547 root 1.272
1548     void cede_to_tick ()
1549 root 1.236 CODE:
1550 root 1.272 coroapi::cede_to_tick ();
1551 root 1.236
1552 root 1.272 NV till_tick ()
1553 root 1.236 CODE:
1554 root 1.272 RETVAL = SvNVX (sv_next_tick) - now ();
1555 root 1.236 OUTPUT:
1556     RETVAL
1557    
1558 root 1.272 int tick_inhibit ()
1559 root 1.236 CODE:
1560 root 1.272 RETVAL = tick_inhibit;
1561 root 1.236 OUTPUT:
1562     RETVAL
1563    
1564 root 1.272 void tick_inhibit_inc ()
1565     CODE:
1566     ++tick_inhibit;
1567    
1568     void tick_inhibit_dec ()
1569     CODE:
1570     if (!--tick_inhibit)
1571     if (tick_pending)
1572     {
1573     ev_async_send (EV_DEFAULT, &tick_watcher);
1574     coroapi::cede ();
1575     }
1576    
1577     void server_tick ()
1578     CODE:
1579     {
1580     NOW = ev_now (EV_DEFAULT);
1581     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1582     SvNV_set (sv_tick_start, NOW); SvNOK_only (sv_tick_start);
1583     runtime = SvNVX (sv_runtime);
1584    
1585     server_tick ();
1586    
1587     NOW = ev_time ();
1588     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1589     runtime += TICK;
1590     SvNV_set (sv_runtime, runtime); SvNOK_only (sv_runtime);
1591     }
1592    
1593 root 1.1 NV floor (NV x)
1594    
1595     NV ceil (NV x)
1596    
1597 root 1.143 NV rndm (...)
1598 root 1.286 ALIAS:
1599     rmg_rndm = 1
1600 root 1.143 CODE:
1601 root 1.286 {
1602     rand_gen &gen = ix ? rmg_rndm : rndm;
1603 root 1.143 switch (items)
1604     {
1605 root 1.286 case 0: RETVAL = gen (); break;
1606     case 1: RETVAL = gen (SvUV (ST (0))); break;
1607     case 2: RETVAL = gen (SvIV (ST (0)), SvIV (ST (1))); break;
1608 root 1.143 default: croak ("cf::rndm requires none, one or two parameters."); break;
1609     }
1610 root 1.286 }
1611 root 1.143 OUTPUT:
1612     RETVAL
1613    
1614 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1615     CODE:
1616     RETVAL = clamp (value, min_value, max_value);
1617     OUTPUT:
1618     RETVAL
1619    
1620     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1621     CODE:
1622     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1623     OUTPUT:
1624     RETVAL
1625    
1626 root 1.268 void weaken (...)
1627     PROTOTYPE: @
1628     CODE:
1629     while (items > 0)
1630     sv_rvweaken (ST (--items));
1631    
1632 root 1.1 void
1633 root 1.198 log_backtrace (utf8_string msg)
1634    
1635     void
1636     LOG (int flags, utf8_string msg)
1637 root 1.1 PROTOTYPE: $$
1638 root 1.198 C_ARGS: flags, "%s", msg
1639 root 1.1
1640 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1641 root 1.1 PROTOTYPE: $$
1642    
1643 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1644 root 1.1 PROTOTYPE: $$
1645    
1646     void
1647     sub_generation_inc ()
1648     CODE:
1649     PL_sub_generation++;
1650    
1651 root 1.183 const_octet_string
1652 root 1.1 mapdir ()
1653     PROTOTYPE:
1654     ALIAS:
1655     mapdir = 0
1656     uniquedir = 1
1657     tmpdir = 2
1658     confdir = 3
1659     localdir = 4
1660     playerdir = 5
1661     datadir = 6
1662     CODE:
1663 root 1.19 switch (ix)
1664     {
1665     case 0: RETVAL = settings.mapdir ; break;
1666     case 1: RETVAL = settings.uniquedir; break;
1667     case 2: RETVAL = settings.tmpdir ; break;
1668     case 3: RETVAL = settings.confdir ; break;
1669     case 4: RETVAL = settings.localdir ; break;
1670     case 5: RETVAL = settings.playerdir; break;
1671     case 6: RETVAL = settings.datadir ; break;
1672     }
1673 root 1.1 OUTPUT: RETVAL
1674    
1675 root 1.120 void abort ()
1676    
1677 root 1.199 void reset_signals ()
1678    
1679 root 1.270 void fork_abort (const_octet_string cause = "cf::fork_abort")
1680 root 1.144
1681 root 1.270 void cleanup (const_octet_string cause, bool make_core = false)
1682 root 1.134
1683 root 1.116 void emergency_save ()
1684    
1685 root 1.156 void _exit (int status = EXIT_SUCCESS)
1686    
1687 root 1.125 #if _POSIX_MEMLOCK
1688    
1689     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1690 root 1.271 INIT:
1691 root 1.279 #if __GLIBC__
1692     mallopt (M_PERTURB, 0xee); // bug-workaround for linux glibc+mlockall+calloc
1693 root 1.277 #endif
1694 root 1.125
1695     int munlockall ()
1696    
1697     #endif
1698    
1699 root 1.279 int
1700     malloc_trim (IV pad = 0)
1701    
1702     void
1703     mallinfo ()
1704     PPCODE:
1705     {
1706     #if __GLIBC__
1707     struct mallinfo mai = mallinfo ();
1708     EXTEND (SP, 10*2);
1709     PUSHs (sv_2mortal (newSVpv ("arena" , 0))); PUSHs (sv_2mortal (newSViv (mai.arena)));
1710     PUSHs (sv_2mortal (newSVpv ("ordblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.ordblks)));
1711     PUSHs (sv_2mortal (newSVpv ("smblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.smblks)));
1712     PUSHs (sv_2mortal (newSVpv ("hblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblks)));
1713     PUSHs (sv_2mortal (newSVpv ("hblkhd" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblkhd)));
1714     PUSHs (sv_2mortal (newSVpv ("usmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.usmblks)));
1715     PUSHs (sv_2mortal (newSVpv ("fsmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.fsmblks)));
1716     PUSHs (sv_2mortal (newSVpv ("uordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.uordblks)));
1717     PUSHs (sv_2mortal (newSVpv ("fordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.fordblks)));
1718     PUSHs (sv_2mortal (newSVpv ("keepcost", 0))); PUSHs (sv_2mortal (newSViv (mai.keepcost)));
1719     #endif
1720     EXTEND (SP, 2*2);
1721     PUSHs (sv_2mortal (newSVpv ("slice_alloc", 0))); PUSHs (sv_2mortal (newSVuv (slice_alloc)));
1722     PUSHs (sv_2mortal (newSVpv ("shstr_alloc", 0))); PUSHs (sv_2mortal (newSVuv (shstr_alloc)));
1723 root 1.282 PUSHs (sv_2mortal (newSVpv ("objects" , 0))); PUSHs (sv_2mortal (newSVuv (objects.size () * sizeof (object))));
1724 root 1.279 }
1725    
1726 root 1.183 int find_animation (utf8_string text)
1727 root 1.1 PROTOTYPE: $
1728    
1729 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1730 root 1.1
1731 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1732 root 1.1
1733     int
1734     exp_to_level (val64 exp)
1735     CODE:
1736     {
1737     int i = 0;
1738    
1739     RETVAL = settings.max_level;
1740    
1741     for (i = 1; i <= settings.max_level; i++)
1742     {
1743     if (levels[i] > exp)
1744     {
1745     RETVAL = i - 1;
1746     break;
1747     }
1748     }
1749     }
1750     OUTPUT: RETVAL
1751    
1752     val64
1753     level_to_min_exp (int level)
1754     CODE:
1755     if (level > settings.max_level)
1756     RETVAL = levels[settings.max_level];
1757     else if (level < 1)
1758     RETVAL = 0;
1759     else
1760     RETVAL = levels[level];
1761     OUTPUT: RETVAL
1762    
1763     SV *
1764     resistance_to_string (int atnr)
1765     CODE:
1766     if (atnr >= 0 && atnr < NROFATTACKS)
1767     RETVAL = newSVpv (resist_plus[atnr], 0);
1768     else
1769     XSRETURN_UNDEF;
1770     OUTPUT: RETVAL
1771    
1772 root 1.275 UUID
1773 root 1.274 uuid_cur ()
1774     CODE:
1775 root 1.275 RETVAL = UUID::cur;
1776 root 1.274 OUTPUT:
1777     RETVAL
1778    
1779 root 1.275 UUID
1780 root 1.274 uuid_gen ()
1781     CODE:
1782 root 1.275 RETVAL = UUID::gen ();
1783     OUTPUT:
1784     RETVAL
1785    
1786     val64
1787     uuid_seq (UUID uuid)
1788     CODE:
1789     RETVAL = uuid.seq;
1790     OUTPUT:
1791     RETVAL
1792    
1793     UUID
1794     uuid_str (val64 seq)
1795     CODE:
1796     RETVAL.seq = seq;
1797 root 1.274 OUTPUT:
1798     RETVAL
1799    
1800     void
1801     coin_names ()
1802     PPCODE:
1803     EXTEND (SP, NUM_COINS);
1804     for (int i = 0; i < NUM_COINS; ++i)
1805     PUSHs (sv_2mortal (newSVpv (coins [i], 0)));
1806    
1807     void
1808     coin_archetypes ()
1809     PPCODE:
1810     EXTEND (SP, NUM_COINS);
1811     for (int i = 0; i < NUM_COINS; ++i)
1812     PUSHs (sv_2mortal (to_sv (archetype::find (coins [i]))));
1813    
1814 root 1.162 bool
1815 root 1.278 load_resource_file_ (octet_string filename)
1816 root 1.162
1817 root 1.97 MODULE = cf PACKAGE = cf::attachable
1818    
1819 root 1.27 int
1820 root 1.97 valid (SV *obj)
1821 root 1.27 CODE:
1822     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1823     OUTPUT:
1824     RETVAL
1825    
1826 root 1.164 void
1827     debug_trace (attachable *obj, bool on = true)
1828     CODE:
1829     obj->flags &= ~attachable::F_DEBUG_TRACE;
1830     if (on)
1831     obj->flags |= attachable::F_DEBUG_TRACE;
1832    
1833 root 1.153 int mortals_size ()
1834     CODE:
1835     RETVAL = attachable::mortals.size ();
1836     OUTPUT: RETVAL
1837    
1838     #object *mortals (U32 index)
1839     # CODE:
1840     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1841     # OUTPUT: RETVAL
1842    
1843 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1844 root 1.115
1845 root 1.101 MODULE = cf PACKAGE = cf::global
1846    
1847     int invoke (SV *klass, int event, ...)
1848     CODE:
1849     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1850     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1851     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1852 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1853 root 1.101 OUTPUT: RETVAL
1854    
1855 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1856    
1857 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1858 root 1.62
1859 root 1.18 int invoke (object *op, int event, ...)
1860     CODE:
1861     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1862 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1863     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1864 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1865 root 1.18 OUTPUT: RETVAL
1866    
1867     SV *registry (object *op)
1868    
1869 root 1.134 int objects_size ()
1870     CODE:
1871     RETVAL = objects.size ();
1872     OUTPUT: RETVAL
1873    
1874     object *objects (U32 index)
1875     CODE:
1876     RETVAL = index < objects.size () ? objects [index] : 0;
1877     OUTPUT: RETVAL
1878    
1879     int actives_size ()
1880     CODE:
1881     RETVAL = actives.size ();
1882     OUTPUT: RETVAL
1883    
1884     object *actives (U32 index)
1885 root 1.57 CODE:
1886 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1887 root 1.57 OUTPUT: RETVAL
1888    
1889 root 1.283 int mortals_size ()
1890     CODE:
1891     RETVAL = attachable::mortals.size ();
1892     OUTPUT: RETVAL
1893    
1894 root 1.215 const char *slot_use_name (U32 slot)
1895 root 1.205 ALIAS:
1896 root 1.215 slot_nonuse_name = 1
1897 root 1.205 CODE:
1898     {
1899     if (slot >= NUM_BODY_LOCATIONS)
1900     croak ("body slot index out of range");
1901    
1902     switch (ix)
1903     {
1904 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1905     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1906 root 1.205 }
1907     }
1908     OUTPUT:
1909     RETVAL
1910    
1911 root 1.1 # missing properties
1912    
1913 root 1.54 object *head (object *op)
1914     PROTOTYPE: $
1915     CODE:
1916 root 1.134 RETVAL = op->head_ ();
1917 root 1.54 OUTPUT: RETVAL
1918    
1919 root 1.1 void
1920     inv (object *obj)
1921     PROTOTYPE: $
1922     PPCODE:
1923     {
1924 root 1.254 for (object *o = obj->inv; o; o = o->below)
1925 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1926 root 1.1 }
1927    
1928 root 1.102 void
1929     set_animation (object *op, int idx)
1930     CODE:
1931     SET_ANIMATION (op, idx);
1932    
1933 elmex 1.160 int
1934     num_animations (object *op)
1935     CODE:
1936     RETVAL = NUM_ANIMATIONS (op);
1937     OUTPUT: RETVAL
1938    
1939 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1940     ALIAS:
1941     slot_used = 1
1942     CODE:
1943     {
1944     if (slot >= NUM_BODY_LOCATIONS)
1945     croak ("body slot index out of range");
1946    
1947 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1948 root 1.205
1949     if (items > 2)
1950     if (ix)
1951 root 1.208 op->slot[slot].used = value;
1952     else
1953 root 1.205 op->slot[slot].info = value;
1954     }
1955     OUTPUT:
1956     RETVAL
1957    
1958 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1959 root 1.58
1960     object *find_marked_object (object *op)
1961    
1962 root 1.109 int need_identify (object *obj);
1963 root 1.1
1964     int apply_shop_mat (object *shop_mat, object *op);
1965    
1966 root 1.27 int move (object *op, int dir, object *originator = op)
1967     CODE:
1968     RETVAL = move_ob (op, dir, originator);
1969     OUTPUT:
1970     RETVAL
1971 root 1.1
1972 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1973     CODE:
1974     manual_apply (applied, applier, flags);
1975 root 1.1
1976 root 1.74 void apply_below (object *op)
1977     CODE:
1978     player_apply_below (op);
1979 root 1.1
1980 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1981    
1982 root 1.74 int pay_item (object *op, object *buyer)
1983     CODE:
1984     RETVAL = pay_for_item (op, buyer);
1985     OUTPUT: RETVAL
1986 root 1.1
1987 root 1.74 int pay_amount (object *op, uint64 amount)
1988     CODE:
1989     RETVAL = pay_for_amount (amount, op);
1990     OUTPUT: RETVAL
1991 root 1.1
1992     void pay_player (object *op, uint64 amount)
1993    
1994 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1995 root 1.1
1996 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1997 root 1.1
1998 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1999     CODE:
2000     do_learn_spell (op, sp, special_prayer);
2001 root 1.1
2002 root 1.74 void forget_spell (object *op, object *sp)
2003     CODE:
2004     do_forget_spell (op, query_name (sp));
2005 root 1.1
2006 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2007 root 1.74 CODE:
2008     RETVAL = check_spell_known (op, spellname);
2009     OUTPUT: RETVAL
2010 root 1.1
2011 root 1.74 int query_money (object *op)
2012 root 1.1 ALIAS: money = 0
2013    
2014 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2015 root 1.1 ALIAS: cost = 0
2016    
2017 root 1.74 void spring_trap (object *op, object *victim)
2018 root 1.1
2019 root 1.74 int check_trigger (object *op, object *cause)
2020 root 1.1
2021 root 1.74 void drop (object *who, object *op)
2022 root 1.1
2023 root 1.74 void pick_up (object *who, object *op)
2024 root 1.1
2025 root 1.102 void update_object (object *op, int action)
2026 root 1.1
2027 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2028 root 1.1
2029     void player_lvl_adj (object *who, object *skill = 0)
2030    
2031     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2032    
2033     int calc_skill_exp (object *who, object *op, object *skill);
2034    
2035     void push_button (object *op);
2036    
2037     void use_trigger (object *op);
2038    
2039 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2040 root 1.1
2041     void remove_button_link (object *op);
2042    
2043 elmex 1.232 void handle_apply_yield (object *op);
2044    
2045 root 1.1
2046     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2047    
2048     # no clean way to get an object from an archetype - stupid idiotic
2049     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2050    
2051 root 1.183 object *new (utf8_string archetype = 0)
2052 root 1.1 PROTOTYPE: ;$
2053     CODE:
2054 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2055 root 1.1 OUTPUT:
2056     RETVAL
2057    
2058 root 1.225 object *find_object (U32 tag)
2059    
2060 root 1.218 # TODO: nuke
2061 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2062 root 1.1 PROTOTYPE: $$$$$$
2063     CODE:
2064     {
2065 root 1.257 RETVAL = insert_ob_in_map_at (ob, where, orig, flag, x, y);
2066 root 1.1 }
2067    
2068 root 1.284 shstr
2069     object::kv_get (shstr key)
2070 root 1.1
2071 root 1.284 void
2072     object::kv_del (shstr key)
2073    
2074     void
2075     object::kv_set (shstr key, shstr value)
2076 root 1.1
2077     object *get_nearest_player (object *ob)
2078     ALIAS: nearest_player = 0
2079     PREINIT:
2080     extern object *get_nearest_player (object *);
2081    
2082     void rangevector (object *ob, object *other, int flags = 0)
2083     PROTOTYPE: $$;$
2084     PPCODE:
2085     {
2086     rv_vector rv;
2087     get_rangevector (ob, other, &rv, flags);
2088     EXTEND (SP, 5);
2089     PUSHs (newSVuv (rv.distance));
2090     PUSHs (newSViv (rv.distance_x));
2091     PUSHs (newSViv (rv.distance_y));
2092     PUSHs (newSViv (rv.direction));
2093 root 1.257 PUSHs (to_sv (rv.part));
2094 root 1.1 }
2095    
2096     bool on_same_map_as (object *ob, object *other)
2097     CODE:
2098     RETVAL = on_same_map (ob, other);
2099     OUTPUT: RETVAL
2100    
2101 root 1.183 const_utf8_string
2102 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2103 root 1.1 CODE:
2104 root 1.58 RETVAL = query_base_name (op, plural);
2105 root 1.1 OUTPUT: RETVAL
2106    
2107 root 1.256 # return the tail of an object, excluding itself
2108     void
2109     tail (object *op)
2110     PPCODE:
2111     while ((op = op->more))
2112     XPUSHs (sv_2mortal (to_sv (op)));
2113    
2114 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2115    
2116     player *player (object *op)
2117     CODE:
2118     RETVAL = op->contr;
2119     OUTPUT: RETVAL
2120    
2121 root 1.257 bool move_player (object *op, int dir)
2122    
2123 root 1.105 void check_score (object *op)
2124    
2125 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2126 root 1.120 CODE:
2127     new_draw_info (flags, 0, op, txt);
2128 root 1.1
2129     void kill_player (object *op)
2130    
2131 root 1.257 void esrv_send_item (object *pl, object *item)
2132    
2133     void esrv_update_item (object *pl, int what, object *item)
2134     C_ARGS: what, pl, item
2135    
2136     void esrv_del_item (object *pl, int tag)
2137     C_ARGS: pl->contr, tag
2138 root 1.58
2139 root 1.183 int command_summon (object *op, utf8_string params)
2140 root 1.67
2141 root 1.183 int command_arrest (object *op, utf8_string params)
2142 root 1.67
2143 root 1.66
2144 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2145 root 1.1
2146 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2147 root 1.62
2148 root 1.18 int invoke (player *pl, int event, ...)
2149     CODE:
2150     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2151 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2152     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2153 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2154 root 1.18 OUTPUT: RETVAL
2155    
2156 root 1.12 SV *registry (player *pl)
2157 root 1.1
2158 root 1.102 void
2159     save_stats (player *pl)
2160     CODE:
2161     pl->ob->stats.hp = pl->ob->stats.maxhp;
2162     pl->ob->stats.sp = pl->ob->stats.maxsp;
2163     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2164     pl->orig_stats = pl->ob->stats;
2165    
2166 root 1.217 void clear_los (player *pl)
2167    
2168 root 1.1 bool
2169     cell_visible (player *pl, int dx, int dy)
2170     CODE:
2171 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2172     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2173 root 1.1 OUTPUT:
2174     RETVAL
2175    
2176 root 1.4 void
2177 root 1.1 send (player *pl, SV *packet)
2178     CODE:
2179     {
2180     STRLEN len;
2181     char *buf = SvPVbyte (packet, len);
2182    
2183 root 1.258 if (len > MAXSOCKBUF)
2184     pl->failmsg ("[packet too long for client]");
2185     else if (pl->ns)
2186 root 1.100 pl->ns->send_packet (buf, len);
2187 root 1.1 }
2188    
2189     int
2190     listening (player *pl, int new_value = -1)
2191     CODE:
2192     RETVAL = pl->listening;
2193     if (new_value >= 0)
2194     pl->listening = new_value;
2195     OUTPUT:
2196     RETVAL
2197    
2198 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2199 root 1.45 PROTOTYPE: $;$$$
2200 root 1.1 PPCODE:
2201 root 1.45 if (GIMME_V != G_VOID)
2202     {
2203     EXTEND (SP, 3);
2204     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2205     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2206     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2207     }
2208 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2209     if (x) sv_to (x, pl->bed_x);
2210     if (y) sv_to (y, pl->bed_y);
2211 root 1.1
2212     void
2213     list ()
2214     PPCODE:
2215 root 1.128 for_all_players (pl)
2216 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2217 root 1.1
2218    
2219     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2220    
2221 root 1.61 int invoke (maptile *map, int event, ...)
2222 root 1.18 CODE:
2223     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2224 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2225     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2226 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2227 root 1.25 OUTPUT: RETVAL
2228 root 1.18
2229 root 1.61 SV *registry (maptile *map)
2230 root 1.12
2231 root 1.255 void
2232     find_tagged_objects (maptile *map, utf8_string tag = 0)
2233     PPCODE:
2234     {
2235     if (!map->spaces)
2236     XSRETURN_EMPTY;
2237    
2238     if (tag)
2239     {
2240     shstr_cmp tag_ (tag);
2241    
2242     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2243     for (object *op = ms->bot; op; op = op->above)
2244     if (op->tag == tag_)
2245     XPUSHs (sv_2mortal (to_sv (op)));
2246     }
2247     else
2248     {
2249     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2250     for (object *op = ms->bot; op; op = op->above)
2251     if (op->tag)
2252     XPUSHs (sv_2mortal (to_sv (op)));
2253     }
2254     }
2255    
2256 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2257 root 1.1
2258 root 1.116 void
2259     maptile::instantiate ()
2260    
2261     maptile *new ()
2262 root 1.1 PROTOTYPE:
2263     CODE:
2264 root 1.116 RETVAL = new maptile;
2265 root 1.1 OUTPUT:
2266     RETVAL
2267    
2268 root 1.116 void
2269 root 1.117 maptile::players ()
2270     PPCODE:
2271     if (GIMME_V == G_SCALAR)
2272 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2273 root 1.117 else if (GIMME_V == G_ARRAY)
2274     {
2275     EXTEND (SP, THIS->players);
2276     for_all_players (pl)
2277     if (pl->ob && pl->ob->map == THIS)
2278 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2279 root 1.117 }
2280    
2281 root 1.156 void
2282 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2283 root 1.156 CODE:
2284     {
2285 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2286     croak ("maptile::add_underlay: palette must be arrayref");
2287 root 1.156
2288 root 1.168 palette = SvRV (palette);
2289 root 1.156
2290 root 1.168 STRLEN idxlen;
2291     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2292 root 1.156
2293 root 1.168 for (int x = 0; x < THIS->width; ++x)
2294     for (int y = 0; y < THIS->height; ++y)
2295     {
2296     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2297     if (op->flag [FLAG_IS_FLOOR])
2298     goto skip_space;
2299    
2300     {
2301     int offs = offset + y * stride + x;
2302     if (IN_RANGE_EXC (offs, 0, idxlen))
2303     {
2304     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2305     {
2306     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2307     ob->flag [FLAG_NO_MAP_SAVE] = true;
2308     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2309 root 1.200
2310     if (ob->randomitems)
2311     {
2312 root 1.203 if (!ob->above)
2313     {
2314     ob->create_treasure (ob->randomitems);
2315    
2316     for (object *op = ob->above; op; op = op->above)
2317     op->flag [FLAG_NO_MAP_SAVE] = true;
2318     }
2319    
2320 root 1.200 ob->randomitems = 0;
2321     }
2322 root 1.168 }
2323     }
2324     }
2325 root 1.156
2326 root 1.168 skip_space: ;
2327     }
2328     }
2329    
2330     void
2331     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2332     CODE:
2333     {
2334     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2335     croak ("maptile::set_regiondata: palette must be arrayref");
2336    
2337     palette = SvRV (palette);
2338    
2339     STRLEN idxlen;
2340     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2341    
2342 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2343 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2344    
2345     for (int i = av_len ((AV *)palette) + 1; i--; )
2346 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2347 root 1.168
2348     for (int y = 0; y < THIS->height; ++y)
2349     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2350    
2351     sfree (THIS->regions, THIS->size ());
2352 root 1.230 delete [] THIS->regionmap;
2353 root 1.168
2354     THIS->regions = regions;
2355 root 1.156 THIS->regionmap = regionmap;
2356     }
2357    
2358 root 1.193 void
2359     maptile::create_region_treasure ()
2360     CODE:
2361     {
2362     object *op = object::create ();
2363     op->type = FLOOR;
2364     op->map = THIS;
2365    
2366     for (int x = 0; x < THIS->width; ++x)
2367     for (int y = 0; y < THIS->height; ++y)
2368     {
2369     region *rgn = THIS->region (x, y);
2370    
2371     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2372     if (rgn->treasure && rndm () < rgn->treasure_density)
2373     {
2374     op->x = x;
2375     op->y = y;
2376     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2377     }
2378     }
2379    
2380     op->destroy ();
2381     }
2382    
2383 root 1.74 int out_of_map (maptile *map, int x, int y)
2384    
2385 root 1.29 void
2386 root 1.61 trigger (maptile *map, long connection, bool state = true)
2387 root 1.29 CODE:
2388     activate_connection (map, connection, state);
2389    
2390     void
2391 root 1.61 get_connection (maptile *map, long connection)
2392 root 1.29 PPCODE:
2393     oblinkpt *obp = get_connection_links (map, connection);
2394     if (obp)
2395     for (objectlink *ol = obp->link; ol; ol = ol->next)
2396 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2397 root 1.1
2398     void
2399 root 1.140 get_map_flags (maptile *map, int x, int y)
2400 root 1.1 PPCODE:
2401     {
2402 root 1.61 maptile *nmap = 0;
2403 root 1.1 I16 nx = 0, ny = 0;
2404 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2405 root 1.1
2406     EXTEND (SP, 4);
2407     PUSHs (sv_2mortal (newSViv (flags)));
2408    
2409     if (GIMME_V == G_ARRAY)
2410     {
2411 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2412 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2413     PUSHs (sv_2mortal (newSViv (ny)));
2414     }
2415     }
2416    
2417     void
2418 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2419 root 1.1 PROTOTYPE: $$$
2420     PPCODE:
2421     {
2422     object *o;
2423 root 1.61 maptile *nmap = 0;
2424 root 1.1 I16 nx, ny;
2425    
2426 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2427 root 1.1
2428     if (nmap)
2429     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2430 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2431 root 1.1 }
2432    
2433     SV *
2434 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2435 root 1.1 PROTOTYPE: $$$
2436     ALIAS:
2437     top_at = 1
2438     flags_at = 2
2439     light_at = 3
2440     move_block_at = 4
2441     move_slow_at = 5
2442     move_on_at = 6
2443     move_off_at = 7
2444     INIT:
2445 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2446 root 1.1 CODE:
2447     switch (ix)
2448     {
2449 root 1.257 case 0: RETVAL = to_sv (GET_MAP_OB (obj, x, y)); break;
2450     case 1: RETVAL = to_sv (GET_MAP_TOP (obj, x, y)); break;
2451     case 2: RETVAL = newSVuv (GET_MAP_FLAGS (obj, x, y)); break;
2452     case 3: RETVAL = newSViv (GET_MAP_LIGHT (obj, x, y)); break;
2453     case 4: RETVAL = newSVuv (GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2454     case 5: RETVAL = newSVuv (GET_MAP_MOVE_SLOW (obj, x, y)); break;
2455     case 6: RETVAL = newSVuv (GET_MAP_MOVE_ON (obj, x, y)); break;
2456     case 7: RETVAL = newSVuv (GET_MAP_MOVE_OFF (obj, x, y)); break;
2457 root 1.1 }
2458 root 1.122 OUTPUT: RETVAL
2459 root 1.1
2460 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2461    
2462     void fix_walls_around (maptile *map, int x, int y)
2463 root 1.1
2464 root 1.117 # worst xs function of my life
2465 root 1.140 bool
2466 root 1.117 _create_random_map (\
2467 root 1.140 maptile *self,\
2468 root 1.183 utf8_string wallstyle,\
2469     utf8_string wall_name,\
2470     utf8_string floorstyle,\
2471     utf8_string monsterstyle,\
2472     utf8_string treasurestyle,\
2473     utf8_string layoutstyle,\
2474     utf8_string doorstyle,\
2475     utf8_string decorstyle,\
2476     utf8_string origin_map,\
2477     utf8_string final_map,\
2478     utf8_string exitstyle,\
2479     utf8_string this_map,\
2480     utf8_string exit_on_final_map,\
2481 root 1.146 int xsize,\
2482     int ysize,\
2483 root 1.117 int expand2x,\
2484     int layoutoptions1,\
2485     int layoutoptions2,\
2486     int layoutoptions3,\
2487     int symmetry,\
2488     int difficulty,\
2489     int difficulty_given,\
2490     float difficulty_increase,\
2491     int dungeon_level,\
2492     int dungeon_depth,\
2493     int decoroptions,\
2494     int orientation,\
2495     int origin_y,\
2496     int origin_x,\
2497 root 1.146 U32 random_seed,\
2498 root 1.117 val64 total_map_hp,\
2499     int map_layout_style,\
2500     int treasureoptions,\
2501     int symmetry_used,\
2502 root 1.137 region *region,\
2503 root 1.183 utf8_string custom\
2504 root 1.117 )
2505     CODE:
2506     {
2507     random_map_params rmp;
2508    
2509     assign (rmp.wallstyle , wallstyle);
2510     assign (rmp.wall_name , wall_name);
2511     assign (rmp.floorstyle , floorstyle);
2512     assign (rmp.monsterstyle , monsterstyle);
2513     assign (rmp.treasurestyle , treasurestyle);
2514     assign (rmp.layoutstyle , layoutstyle);
2515     assign (rmp.doorstyle , doorstyle);
2516     assign (rmp.decorstyle , decorstyle);
2517     assign (rmp.exitstyle , exitstyle);
2518     assign (rmp.exit_on_final_map, exit_on_final_map);
2519    
2520 root 1.122 rmp.origin_map = origin_map;
2521     rmp.final_map = final_map;
2522     rmp.this_map = this_map;
2523 root 1.146 rmp.xsize = xsize;
2524     rmp.ysize = ysize;
2525 root 1.117 rmp.expand2x = expand2x;
2526     rmp.layoutoptions1 = layoutoptions1;
2527     rmp.layoutoptions2 = layoutoptions2;
2528     rmp.layoutoptions3 = layoutoptions3;
2529     rmp.symmetry = symmetry;
2530     rmp.difficulty = difficulty;
2531     rmp.difficulty_given = difficulty_given;
2532     rmp.difficulty_increase = difficulty_increase;
2533     rmp.dungeon_level = dungeon_level;
2534     rmp.dungeon_depth = dungeon_depth;
2535     rmp.decoroptions = decoroptions;
2536     rmp.orientation = orientation;
2537     rmp.origin_y = origin_y;
2538     rmp.origin_x = origin_x;
2539     rmp.random_seed = random_seed;
2540 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2541 root 1.117 rmp.map_layout_style = map_layout_style;
2542     rmp.treasureoptions = treasureoptions;
2543     rmp.symmetry_used = symmetry_used;
2544     rmp.region = region;
2545 root 1.137 rmp.custom = custom;
2546 root 1.117
2547 root 1.140 RETVAL = self->generate_random_map (&rmp);
2548 root 1.117 }
2549     OUTPUT:
2550     RETVAL
2551    
2552 root 1.19 MODULE = cf PACKAGE = cf::arch
2553 root 1.1
2554 root 1.218 int archetypes_size ()
2555     CODE:
2556     RETVAL = archetypes.size ();
2557     OUTPUT: RETVAL
2558    
2559     archetype *archetypes (U32 index)
2560     CODE:
2561     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2562     OUTPUT: RETVAL
2563 root 1.1
2564 root 1.212 object *instantiate (archetype *arch)
2565     CODE:
2566     RETVAL = arch_to_object (arch);
2567     OUTPUT:
2568     RETVAL
2569    
2570 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2571 root 1.1
2572 root 1.19 MODULE = cf PACKAGE = cf::party
2573 root 1.1
2574 root 1.19 partylist *first ()
2575 root 1.1 PROTOTYPE:
2576 root 1.19 CODE:
2577     RETVAL = get_firstparty ();
2578     OUTPUT: RETVAL
2579 root 1.1
2580 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2581 root 1.1
2582 root 1.19 MODULE = cf PACKAGE = cf::region
2583 root 1.1
2584 root 1.161 void
2585     list ()
2586     PPCODE:
2587     for_all_regions (rgn)
2588     XPUSHs (sv_2mortal (to_sv (rgn)));
2589    
2590 root 1.183 region *find (utf8_string name)
2591 root 1.161 PROTOTYPE: $
2592 root 1.19 CODE:
2593 root 1.161 RETVAL = region::find (name);
2594 root 1.19 OUTPUT: RETVAL
2595 root 1.1
2596 root 1.183 region *find_fuzzy (utf8_string name)
2597 root 1.122 PROTOTYPE: $
2598     CODE:
2599 root 1.161 RETVAL = region::find_fuzzy (name);
2600 root 1.122 OUTPUT: RETVAL
2601    
2602 root 1.186 int specificity (region *rgn)
2603     CODE:
2604     RETVAL = 0;
2605     while (rgn = rgn->parent)
2606     RETVAL++;
2607     OUTPUT: RETVAL
2608    
2609 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2610 root 1.1
2611 root 1.19 MODULE = cf PACKAGE = cf::living
2612 root 1.1
2613 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2614 root 1.1
2615 root 1.76 MODULE = cf PACKAGE = cf::settings
2616    
2617 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2618 root 1.76
2619 root 1.84 MODULE = cf PACKAGE = cf::client
2620 root 1.79
2621 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2622 root 1.79
2623 root 1.84 int invoke (client *ns, int event, ...)
2624 root 1.79 CODE:
2625 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2626 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2627     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2628 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2629 root 1.79 OUTPUT: RETVAL
2630    
2631 root 1.84 SV *registry (client *ns)
2632 root 1.79
2633 root 1.100 void
2634     list ()
2635     PPCODE:
2636     EXTEND (SP, clients.size ());
2637     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2638     PUSHs (sv_2mortal (to_sv (*i)));
2639    
2640 root 1.88 void
2641 root 1.100 client::send_packet (SV *packet)
2642     CODE:
2643     {
2644     STRLEN len;
2645     char *buf = SvPVbyte (packet, len);
2646    
2647 root 1.258 if (len > MAXSOCKBUF)
2648     {
2649     // ugly
2650     if (THIS->pl)
2651     THIS->pl->failmsg ("[packet too long for client]");
2652     }
2653     else
2654     THIS->send_packet (buf, len);
2655 root 1.100 }
2656    
2657 root 1.237 faceidx
2658 root 1.238 client::need_face (utf8_string name, int pri = 0)
2659 root 1.237 CODE:
2660 root 1.238 RETVAL = face_find (name, 0);
2661     if (RETVAL)
2662     {
2663     THIS->send_face (RETVAL, pri);
2664     THIS->flush_fx ();
2665     }
2666     OUTPUT:
2667     RETVAL
2668    
2669     int
2670     client::fx_want (int idx, int value = -1)
2671     CODE:
2672     if (0 < idx && idx < FT_NUM)
2673     {
2674     RETVAL = THIS->fx_want [idx];
2675     if (items > 2)
2676     THIS->fx_want [idx] = value;
2677     }
2678     else
2679     RETVAL = 0;
2680 root 1.237 OUTPUT:
2681     RETVAL
2682    
2683 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2684    
2685     faceidx sound_find (utf8_string name)
2686    
2687 root 1.240 void sound_set (utf8_string str, faceidx face)
2688    
2689     # dire hack
2690     void old_sound_index (int idx, faceidx face)
2691     CODE:
2692     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2693     old_sound_index [idx] = face;
2694    
2695 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2696    
2697 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2698 root 1.176
2699 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2700 root 1.176
2701 root 1.183 faceidx alloc (utf8_string name)
2702 root 1.176 CODE:
2703     {
2704     do
2705     {
2706     RETVAL = faces.size ();
2707 root 1.177 faces.resize (RETVAL + 1);
2708 root 1.176 }
2709     while (!RETVAL); // crude way to leave index 0
2710    
2711     faces [RETVAL].name = name;
2712     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2713    
2714     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2715     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2716     }
2717     OUTPUT: RETVAL
2718    
2719 root 1.227 void set_type (faceidx idx, int value)
2720     ALIAS:
2721     set_type = 0
2722     set_visibility = 1
2723     set_magicmap = 2
2724     set_smooth = 3
2725     set_smoothlevel = 4
2726 root 1.176 CODE:
2727 root 1.229 faceinfo *f = face_info (idx); assert (f);
2728 root 1.227 switch (ix)
2729     {
2730     case 0: f->type = value; break;
2731     case 1: f->visibility = value; break;
2732     case 2: f->magicmap = value; break;
2733     case 3: f->smooth = value; break;
2734     case 4: f->smoothlevel = value; break;
2735     }
2736 root 1.177
2737     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2738 root 1.176 CODE:
2739 root 1.182 {
2740 root 1.231 faceinfo *f = face_info (idx); assert (f);
2741     facedata *d = &(faceset ? f->data64 : f->data32);
2742 root 1.181 sv_to (data, d->data);
2743     STRLEN clen;
2744     char *cdata = SvPVbyte (chksum, clen);
2745 root 1.182 clen = min (CHKSUM_SIZE, clen);
2746    
2747     if (memcmp (d->chksum, cdata, clen))
2748     {
2749     memcpy (d->chksum, cdata, clen);
2750    
2751     // invalidate existing client face info
2752     for_all_clients (ns)
2753     if (ns->faceset == faceset)
2754     {
2755     ns->faces_sent [idx] = false;
2756     ns->force_newmap = true;
2757     }
2758     }
2759     }
2760 root 1.176
2761 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2762     CODE:
2763 root 1.267 facedata *d = face_data (idx, faceset);
2764     if (!d) XSRETURN_UNDEF;
2765 root 1.229 RETVAL = d->data.size ();
2766     OUTPUT:
2767     RETVAL
2768    
2769     SV *get_chksum (faceidx idx, int faceset = 0)
2770     CODE:
2771 root 1.267 facedata *d = face_data (idx, faceset);
2772     if (!d) XSRETURN_UNDEF;
2773 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2774     OUTPUT:
2775     RETVAL
2776    
2777 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2778     CODE:
2779     facedata *d = face_data (idx, faceset);
2780     if (!d) XSRETURN_UNDEF;
2781     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2782     OUTPUT:
2783     RETVAL
2784    
2785 root 1.177 void invalidate (faceidx idx)
2786     CODE:
2787     for_all_clients (ns)
2788 root 1.182 {
2789     ns->faces_sent [idx] = false;
2790     ns->force_newmap = true;
2791     }
2792 root 1.177
2793     void invalidate_all ()
2794     CODE:
2795     for_all_clients (ns)
2796 root 1.182 {
2797     ns->faces_sent.reset ();
2798     ns->force_newmap = true;
2799     }
2800 root 1.177
2801 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2802    
2803     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2804    
2805     animidx anim_find (utf8_string name)
2806     CODE:
2807     RETVAL = animation::find (name).number;
2808     OUTPUT: RETVAL
2809    
2810     animidx set (utf8_string name, SV *frames, int facings = 1)
2811     CODE:
2812     {
2813     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2814     croak ("frames must be an arrayref");
2815    
2816     AV *av = (AV *)SvRV (frames);
2817    
2818     animation *anim = &animation::find (name);
2819     if (anim->number)
2820     {
2821     anim->resize (av_len (av) + 1);
2822     anim->facings = facings;
2823     }
2824     else
2825     anim = &animation::create (name, av_len (av) + 1, facings);
2826    
2827     for (int i = 0; i < anim->num_animations; ++i)
2828     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2829     }
2830     OUTPUT: RETVAL
2831    
2832     void invalidate_all ()
2833     CODE:
2834     for_all_clients (ns)
2835     ns->anims_sent.reset ();
2836    
2837 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2838    
2839     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2840    
2841     SV *
2842     new (char *klass)
2843     CODE:
2844     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2845     OUTPUT: RETVAL
2846    
2847     void
2848     DESTROY (SV *sv)
2849     CODE:
2850     object_freezer *self;
2851     sv_to (sv, self);
2852     delete self;
2853    
2854     MODULE = cf PACKAGE = cf::object::thawer
2855    
2856     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2857    
2858     SV *
2859     new_from_file (char *klass, octet_string path)
2860     CODE:
2861     object_thawer *f = new object_thawer (path);
2862     if (!*f)
2863     {
2864     delete f;
2865     XSRETURN_UNDEF;
2866     }
2867     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2868     OUTPUT: RETVAL
2869    
2870     void
2871     DESTROY (SV *sv)
2872     CODE:
2873     object_thawer *self;
2874     sv_to (sv, self);
2875     delete self;
2876    
2877 root 1.252 void
2878 root 1.253 extract_tags (object_thawer *self)
2879 root 1.254 PPCODE:
2880 root 1.252 while (self->kw != KW_EOF)
2881     {
2882 root 1.254 PUTBACK;
2883 root 1.272 coroapi::cede_to_tick ();
2884 root 1.254 SPAGAIN;
2885 root 1.253
2886 root 1.252 if (self->kw == KW_tag)
2887 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
2888 root 1.252
2889     self->skip ();
2890     }
2891