ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.274
Committed: Thu Apr 10 15:35:16 2008 UTC (16 years, 2 months ago) by root
Branch: MAIN
Changes since 1.273: +28 -0 lines
Log Message:
*** empty log message ***

File Contents

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