ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.291
Committed: Sun Jun 15 20:32:51 2008 UTC (15 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-2_6
Changes since 1.290: +10 -2 lines
Log Message:
*** empty log message ***

File Contents

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