ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.278
Committed: Sun Apr 20 00:44:13 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
Changes since 1.277: +1 -1 lines
Log Message:
reloadable archetypes, maybe

File Contents

# User Rev Content
1 root 1.1 /*
2 root 1.264 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.216 *
4 root 1.272 * Copyright (©) 2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.216 * Copyright (©) 2001-2005,2007 by Chachkoff Yann
6     * Copyright (©) 2006,2007 by Marc Lehmann <cf@schmorp.de>
7     *
8 root 1.264 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.226 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 root 1.216 *
13 root 1.226 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 root 1.216 *
18 root 1.226 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.216 *
21 root 1.264 * The authors can be reached via e-mail to <support@deliantra.net>
22 root 1.106 */
23 root 1.1
24 root 1.198 #include "autoconf.h"
25    
26 root 1.1 #define PLUGIN_NAME "perl"
27 root 1.13 #define PLUGIN_VERSION "cfperl 0.5"
28 root 1.1
29 root 1.198 #if HAVE_EXECINFO_H
30     # include <execinfo.h>
31     #endif
32    
33 root 1.6 #include <cstdarg>
34 root 1.1
35 root 1.257 #include "global.h"
36 root 1.162 #include "loader.h"
37 root 1.257 #include "../random_maps/random_map.h"
38 root 1.272 #include "evthread.h"
39     #include "sproto.h"
40 root 1.1
41 root 1.125 #include <unistd.h>
42     #if _POSIX_MEMLOCK
43     # include <sys/mman.h>
44     #endif
45    
46 root 1.259 #if HAVE_MALLOC_H
47     # include <malloc.h>
48     #endif
49    
50 root 1.32 #include <EXTERN.h>
51     #include <perl.h>
52     #include <XSUB.h>
53    
54 root 1.107 #include "CoroAPI.h"
55 root 1.1 #include "perlxsi.c"
56    
57     extern sint64 *levels; // the experience table
58    
59 root 1.247 typedef object_thawer &object_thawer_ref;
60     typedef object_freezer &object_freezer_ref;
61 root 1.183
62 root 1.194 typedef std::string std__string;
63    
64 root 1.1 static PerlInterpreter *perl;
65    
66 root 1.220 tstamp NOW, runtime;
67 root 1.116
68 root 1.272 static int tick_inhibit;
69     static int tick_pending;
70    
71 root 1.109 global gbl_ev;
72     static AV *cb_global, *cb_attachable, *cb_object, *cb_player, *cb_client, *cb_type, *cb_map;
73 root 1.272 static SV *sv_runtime, *sv_tick_start, *sv_next_tick, *sv_now;
74 root 1.109
75 root 1.210 bitset<NUM_EVENT_TYPES> ev_want_event;
76     bitset<NUM_TYPES> ev_want_type;
77    
78 root 1.109 static HV
79     *stash_cf,
80     *stash_cf_object_wrap,
81     *stash_cf_object_player_wrap,
82     *stash_cf_player_wrap,
83     *stash_cf_map_wrap,
84     *stash_cf_client_wrap,
85     *stash_cf_arch_wrap,
86     *stash_cf_party_wrap,
87     *stash_cf_region_wrap,
88     *stash_cf_living_wrap;
89    
90 root 1.246 static inline SV *
91     newSVpv_utf8 (const char *s)
92     {
93 root 1.252 if (!s)
94     return newSV (0);
95    
96 root 1.246 SV *sv = newSVpv (s, 0);
97     SvUTF8_on (sv);
98     return sv;
99     }
100    
101     static inline SV *
102     newSVpvn_utf8 (const char *s, STRLEN l)
103     {
104 root 1.252 if (!s)
105     return newSV (0);
106    
107 root 1.246 SV *sv = newSVpvn (s, l);
108     SvUTF8_on (sv);
109     return sv;
110     }
111    
112 root 1.109 // helper cast function, returns super class * or 0
113     template<class super>
114     static super *
115     is_a (attachable *at)
116     {
117     //return dynamic_cast<super *>(at); // slower, safer
118     if (typeid (*at) == typeid (super))
119     return static_cast<super *>(at);
120     else
121     return 0;
122     }
123    
124     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125    
126     unordered_vector<attachable *> attachable::mortals;
127    
128 root 1.129 attachable::~attachable ()
129 root 1.109 {
130 root 1.133 assert (!self);
131 root 1.153 assert (!cb);
132 root 1.109 }
133    
134 root 1.130 int
135     attachable::refcnt_cnt () const
136     {
137 root 1.152 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
138 root 1.130 }
139    
140     void
141 root 1.155 attachable::sever_self ()
142 root 1.109 {
143 root 1.164 if (HV *self = this->self)
144 root 1.129 {
145 root 1.155 // keep a refcount because sv_unmagic might call attachable_free,
146     // which might clear self, causing sv_unmagic to crash on a now
147     // invalid object.
148 root 1.154 SvREFCNT_inc (self);
149 root 1.155 hv_clear (self);
150     sv_unmagic ((SV *)self, PERL_MAGIC_ext);
151 root 1.154 SvREFCNT_dec (self);
152 root 1.155
153     // self *must* be null now because thats sv_unmagic's job.
154 root 1.164 assert (!this->self);
155 root 1.129 }
156 root 1.109 }
157    
158 root 1.155 void
159     attachable::optimise ()
160     {
161     if (self
162     && SvREFCNT (self) == 1
163     && !HvTOTALKEYS (self))
164     sever_self ();
165     }
166    
167 root 1.109 // check wether the object really is dead
168     void
169     attachable::do_check ()
170     {
171 root 1.152 if (refcnt_cnt () > 0)
172 root 1.109 return;
173    
174 root 1.133 destroy ();
175 root 1.109 }
176    
177     void
178     attachable::do_destroy ()
179     {
180 root 1.214 INVOKE_ATTACHABLE (DESTROY, this);
181 root 1.109
182 root 1.153 if (cb)
183     {
184     SvREFCNT_dec (cb);
185     cb = 0;
186     }
187    
188 root 1.109 mortals.push_back (this);
189     }
190    
191     void
192     attachable::destroy ()
193     {
194     if (destroyed ())
195     return;
196    
197     flags |= F_DESTROYED;
198     do_destroy ();
199 root 1.198 sever_self ();
200 root 1.109 }
201    
202 root 1.130 void
203     attachable::check_mortals ()
204 root 1.109 {
205 root 1.150 static int i = 0;
206    
207     for (;;)
208 root 1.109 {
209 root 1.150 if (i >= mortals.size ())
210     {
211     i = 0;
212    
213 root 1.221 if (mortals.size () >= 512)
214     {
215     static int last_mortalcount;
216     if (mortals.size () != last_mortalcount)
217     {
218     last_mortalcount = mortals.size ();
219     LOG (llevInfo, "%d mortals.\n", (int)mortals.size ());
220    
221     if (0)
222     {
223     for (int j = 0; j < mortals.size (); ++j)//D
224     fprintf (stderr, "%d:%s %p ", j, &((object *)mortals[j])->name, mortals[j]);//D
225     fprintf (stderr, "\n");//D
226     }
227     }
228     }
229 root 1.150
230     break;
231     }
232    
233 root 1.109 attachable *obj = mortals [i];
234    
235 root 1.197 #if 0
236     if (obj->self)//D make this an assert later
237     {
238     LOG (llevError, "check_mortals: object '%s' still has self\n", typeid (obj).name ());
239     obj->sever_self ();
240     }
241     #endif
242 root 1.109
243 root 1.198 if (obj->refcnt)
244 root 1.109 {
245 root 1.150 ++i; // further delay freeing
246 root 1.109
247 root 1.150 if (!(i & 0x3ff))
248     break;
249     }
250 root 1.109 else
251     {
252 root 1.112 mortals.erase (i);
253 root 1.197 obj->sever_self ();
254 root 1.109 delete obj;
255     }
256     }
257     }
258    
259 root 1.228 void
260 root 1.246 attachable::set_key (const char *key, const char *value, bool is_utf8)
261 root 1.228 {
262     if (!self)
263     self = newHV ();
264    
265     if (value)
266 root 1.246 hv_store (self, key, strlen (key), is_utf8 ? newSVpv_utf8 (value) : newSVpv (value, 0), 0);
267 root 1.228 else
268     hv_delete (self, key, strlen (key), G_DISCARD);
269     }
270    
271 root 1.109 attachable &
272     attachable::operator =(const attachable &src)
273     {
274     //if (self || cb)
275     //INVOKE_OBJECT (CLONE, this, ARG_OBJECT (dst));
276    
277     attach = src.attach;
278     return *this;
279     }
280 root 1.8
281 root 1.221 template<typename T>
282     static bool
283     find_backref (void *ptr, T *obj)
284     {
285     char *s = (char *)obj;
286     while (s < (char *)obj + sizeof (T))
287     {
288     if (ptr == *(void **)s)
289     return true;
290    
291     s += sizeof (void *); // assume natural alignment
292     }
293    
294     return false;
295     }
296    
297     // for debugging, find "live" objects containing this ptr
298     void
299     find_backref (void *ptr)
300     {
301     for_all_objects (op)
302     if (find_backref (ptr, op))
303     fprintf (stderr, "O %p %d:'%s'\n", op, op->count, &op->name);
304    
305     for_all_players (pl)
306     if (find_backref (ptr, pl))
307     fprintf (stderr, "P %p\n", pl);
308    
309     for_all_clients (ns)
310     if (find_backref (ptr, ns))
311     fprintf (stderr, "C %p\n", ns);
312    
313     }
314    
315 root 1.1 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316    
317     static SV *
318 root 1.109 newSVptr (void *ptr, HV *stash, HV *hv = newHV ())
319 root 1.1 {
320     SV *sv;
321    
322     if (!ptr)
323 root 1.252 return newSV (0);
324 root 1.1
325 root 1.109 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, 0, (char *)ptr, 0);
326     return sv_bless (newRV_noinc ((SV *)hv), stash);
327     }
328    
329     static int
330     attachable_free (pTHX_ SV *sv, MAGIC *mg)
331     {
332     attachable *at = (attachable *)mg->mg_ptr;
333 root 1.153
334     //TODO: check if transaction behaviour is really required here
335     if (SV *self = (SV *)at->self)
336     {
337     at->self = 0;
338     SvREFCNT_dec (self);
339     }
340    
341 root 1.111 // next line makes sense, but most objects still have refcnt 0 by default
342     //at->refcnt_chk ();
343 root 1.109 return 0;
344 root 1.1 }
345    
346 root 1.116 MGVTBL attachable::vtbl = {0, 0, 0, 0, attachable_free};
347 root 1.109
348 root 1.116 static SV *
349 root 1.109 newSVattachable (attachable *obj, HV *stash)
350 root 1.11 {
351     if (!obj)
352 root 1.252 return newSV (0);
353 root 1.11
354     if (!obj->self)
355 root 1.228 obj->self = newHV ();
356    
357     if (!SvOBJECT (obj->self))
358 root 1.109 {
359 root 1.116 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
360 root 1.11
361 root 1.129 // now bless the object _once_
362 root 1.228 //TODO: create a class registry with c++ type<=>perl name<=>stash and use it here and elsewhere
363 root 1.129 return sv_bless (newRV_inc ((SV *)obj->self), stash);
364 root 1.109 }
365 root 1.129 else
366 root 1.140 {
367     SV *sv = newRV_inc ((SV *)obj->self);
368    
369     if (Gv_AMG (stash)) // handle overload correctly, as the perl core does not
370     SvAMAGIC_on (sv);
371    
372     return sv;
373     }
374 root 1.11 }
375    
376 root 1.1 static void
377     clearSVptr (SV *sv)
378     {
379     if (SvROK (sv))
380     sv = SvRV (sv);
381    
382     hv_clear ((HV *)sv);
383     sv_unmagic (sv, PERL_MAGIC_ext);
384     }
385    
386     static long
387     SvPTR (SV *sv, const char *klass)
388     {
389     if (!sv_derived_from (sv, klass))
390     croak ("object of type %s expected", klass);
391    
392     MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
393    
394     if (!mg)
395     croak ("perl code used %s object, but C object is already destroyed, caught", klass);
396    
397     return (long)mg->mg_ptr;
398     }
399    
400     static long
401     SvPTR_ornull (SV *sv, const char *klass)
402     {
403     if (SvOK (sv))
404     return SvPTR (sv, klass);
405     else
406     return 0;
407     }
408    
409 root 1.252 inline SV *to_sv (const shstr & v) { return newSVpvn_utf8 ((const char *)v, v.length ()); }
410     inline SV *to_sv (const char * v) { return v ? newSVpv (v, 0) : newSV (0); }
411 root 1.45 inline SV *to_sv (bool v) { return newSViv (v); }
412     inline SV *to_sv ( signed char v) { return newSViv (v); }
413     inline SV *to_sv (unsigned char v) { return newSViv (v); }
414     inline SV *to_sv ( signed short v) { return newSViv (v); }
415     inline SV *to_sv (unsigned short v) { return newSVuv (v); }
416     inline SV *to_sv ( signed int v) { return newSViv (v); }
417     inline SV *to_sv (unsigned int v) { return newSVuv (v); }
418     inline SV *to_sv ( signed long v) { return newSViv (v); }
419     inline SV *to_sv (unsigned long v) { return newSVuv (v); }
420 root 1.48 inline SV *to_sv ( signed long long v) { return newSVval64 (v); }
421     inline SV *to_sv (unsigned long long v) { return newSVval64 (v); }
422 root 1.45 inline SV *to_sv (float v) { return newSVnv (v); }
423     inline SV *to_sv (double v) { return newSVnv (v); }
424 root 1.109 inline SV *to_sv (client * v) { return newSVattachable (v, stash_cf_client_wrap); }
425     inline SV *to_sv (player * v) { return newSVattachable (v, stash_cf_player_wrap); }
426     inline SV *to_sv (object * v) { return newSVattachable (v, v && v->type == PLAYER ? stash_cf_object_player_wrap : stash_cf_object_wrap); }
427     inline SV *to_sv (maptile * v) { return newSVattachable (v, stash_cf_map_wrap); }
428     inline SV *to_sv (archetype * v) { return newSVattachable (v, stash_cf_arch_wrap); }
429 root 1.228 inline SV *to_sv (region * v) { return newSVattachable (v, stash_cf_region_wrap); }
430 root 1.109 inline SV *to_sv (partylist * v) { return newSVptr (v, stash_cf_party_wrap); }
431     inline SV *to_sv (living * v) { return newSVptr (v, stash_cf_living_wrap); }
432 root 1.45
433     inline SV *to_sv (object & v) { return to_sv (&v); }
434     inline SV *to_sv (living & v) { return to_sv (&v); }
435    
436 root 1.194 inline SV *to_sv (const std::string & v) { return newSVpvn (v.data (), v.size ()); }
437     inline SV *to_sv (const treasurelist *v) { return to_sv (v->name); }
438 root 1.45
439 root 1.275 inline SV *to_sv (UUID v) { return newSVpv (v.c_str (), 0); }
440 elmex 1.68
441 root 1.247 inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPVutf8_nolen (sv) : 0; }
442     inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; }
443     inline void sv_to (SV *sv, bool &v) { v = SvIV (sv); }
444     inline void sv_to (SV *sv, signed char &v) { v = SvIV (sv); }
445     inline void sv_to (SV *sv, unsigned char &v) { v = SvIV (sv); }
446     inline void sv_to (SV *sv, signed short &v) { v = SvIV (sv); }
447     inline void sv_to (SV *sv, unsigned short &v) { v = SvIV (sv); }
448     inline void sv_to (SV *sv, signed int &v) { v = SvIV (sv); }
449     inline void sv_to (SV *sv, unsigned int &v) { v = SvUV (sv); }
450     inline void sv_to (SV *sv, signed long &v) { v = SvIV (sv); }
451     inline void sv_to (SV *sv, unsigned long &v) { v = SvUV (sv); }
452 root 1.53 inline void sv_to (SV *sv, signed long long &v) { v = ( signed long long)SvVAL64 (sv); }
453     inline void sv_to (SV *sv, unsigned long long &v) { v = (unsigned long long)SvVAL64 (sv); }
454 root 1.247 inline void sv_to (SV *sv, float &v) { v = SvNV (sv); }
455     inline void sv_to (SV *sv, double &v) { v = SvNV (sv); }
456     inline void sv_to (SV *sv, client * &v) { v = (client *)(attachable *)SvPTR_ornull (sv, "cf::client"); }
457     inline void sv_to (SV *sv, player * &v) { v = (player *)(attachable *)SvPTR_ornull (sv, "cf::player"); }
458     inline void sv_to (SV *sv, object * &v) { v = (object *)(attachable *)SvPTR_ornull (sv, "cf::object"); }
459     inline void sv_to (SV *sv, archetype * &v) { v = (archetype *)(attachable *)SvPTR_ornull (sv, "cf::arch"); }
460     inline void sv_to (SV *sv, maptile * &v) { v = (maptile *)(attachable *)SvPTR_ornull (sv, "cf::map"); }
461     inline void sv_to (SV *sv, region * &v) { v = (region *)(attachable *)SvPTR_ornull (sv, "cf::region"); }
462     inline void sv_to (SV *sv, attachable * &v) { v = (attachable *)SvPTR_ornull (sv, "cf::attachable"); }
463     inline void sv_to (SV *sv, partylist * &v) { v = (partylist *)SvPTR_ornull (sv, "cf::party"); }
464     inline void sv_to (SV *sv, living * &v) { v = (living *)SvPTR_ornull (sv, "cf::living"); }
465     inline void sv_to (SV *sv, object_freezer * &v) { v = (object_freezer *)SvPTR_ornull (sv, "cf::object::freezer"); }
466     inline void sv_to (SV *sv, object_thawer * &v) { v = (object_thawer *)SvPTR_ornull (sv, "cf::object::thawer" ); }
467 root 1.45
468 root 1.247 //inline void sv_to (SV *sv, faceinfo * &v) { v = &faces [face_find (SvPV_nolen (sv), 0)]; }
469     inline void sv_to (SV *sv, treasurelist * &v) { v = treasurelist::find (SvPV_nolen (sv)); }
470 root 1.45
471 root 1.52 template<class T>
472 root 1.247 inline void sv_to (SV *sv, refptr<T> &v) { T *tmp; sv_to (sv, tmp); v = tmp; }
473 root 1.52
474 root 1.45 template<int N>
475 root 1.55 inline void sv_to (SV *sv, char (&v)[N]) { assign (v, SvPV_nolen (sv)); }
476 root 1.45
477 root 1.247 inline void sv_to (SV *sv, bowtype_t &v) { v = (bowtype_t) SvIV (sv); }
478     inline void sv_to (SV *sv, petmode_t &v) { v = (petmode_t) SvIV (sv); }
479     inline void sv_to (SV *sv, usekeytype &v) { v = (usekeytype) SvIV (sv); }
480     inline void sv_to (SV *sv, unapplymode &v) { v = (unapplymode) SvIV (sv); }
481 root 1.106
482 root 1.247 inline void sv_to (SV *sv, std::string &v)
483 root 1.176 {
484     STRLEN len;
485     char *data = SvPVbyte (sv, len);
486     v.assign (data, len);
487     }
488    
489 root 1.247 inline void sv_to (SV *sv, UUID &v)
490 root 1.69 {
491 root 1.275 if (!v.parse (SvPV_nolen (sv)))
492 root 1.69 croak ("unparsable uuid: %s", SvPV_nolen (sv));
493 elmex 1.68 }
494    
495 root 1.109 inline void sv_to (SV *sv, object::flags_t::reference v) { v = SvTRUE (sv); }
496 root 1.106
497 root 1.1 static SV *
498 root 1.6 newSVdt_va (va_list &ap, data_type type)
499 root 1.1 {
500     SV *sv;
501    
502     switch (type)
503     {
504 root 1.10 case DT_INT:
505     sv = newSViv (va_arg (ap, int));
506     break;
507    
508     case DT_INT64:
509     sv = newSVval64 ((val64)va_arg (ap, sint64));
510     break;
511    
512 root 1.6 case DT_DOUBLE:
513 root 1.10 sv = newSVnv (va_arg (ap, double));
514 root 1.1 break;
515    
516 root 1.6 case DT_STRING:
517     {
518 root 1.10 char *str = (char *)va_arg (ap, const char *);
519 root 1.252 sv = str ? newSVpv (str, 0) : newSV (0);
520 root 1.6 }
521 root 1.1 break;
522    
523 root 1.6 case DT_DATA:
524 root 1.1 {
525 root 1.10 char *str = (char *)va_arg (ap, const void *);
526 root 1.6 int len = va_arg (ap, int);
527 root 1.252 sv = str ? newSVpv (str, len) : newSV (0);
528 root 1.1 }
529     break;
530    
531 root 1.6 case DT_OBJECT:
532 root 1.45 sv = to_sv (va_arg (ap, object *));
533 root 1.1 break;
534    
535 root 1.6 case DT_MAP:
536 root 1.11 // va_arg (object *) when void * is passed is an XSI extension
537 root 1.61 sv = to_sv (va_arg (ap, maptile *));
538 root 1.1 break;
539    
540 root 1.88 case DT_CLIENT:
541 root 1.84 sv = to_sv (va_arg (ap, client *));
542 root 1.79 break;
543    
544 root 1.6 case DT_PLAYER:
545 root 1.45 sv = to_sv (va_arg (ap, player *));
546 root 1.1 break;
547    
548 root 1.6 case DT_ARCH:
549 root 1.45 sv = to_sv (va_arg (ap, archetype *));
550 root 1.1 break;
551    
552 root 1.6 case DT_PARTY:
553 root 1.45 sv = to_sv (va_arg (ap, partylist *));
554 root 1.1 break;
555    
556 root 1.6 case DT_REGION:
557 root 1.45 sv = to_sv (va_arg (ap, region *));
558 root 1.1 break;
559    
560     default:
561 root 1.6 assert (("unhandled type in newSVdt_va", 0));
562     }
563    
564     return sv;
565     }
566    
567     static SV *
568     newSVdt (data_type type, ...)
569     {
570     va_list ap;
571    
572     va_start (ap, type);
573     SV *sv = newSVdt_va (ap, type);
574     va_end (ap);
575    
576     return sv;
577     }
578    
579 root 1.11 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
580    
581 root 1.12 SV *
582 root 1.109 registry (attachable *ext)
583 root 1.12 {
584 root 1.13 if (!ext->cb)
585     ext->cb = newAV ();
586 root 1.12
587 root 1.13 return newRV_inc ((SV *)ext->cb);
588 root 1.12 }
589    
590 root 1.13 /////////////////////////////////////////////////////////////////////////////
591    
592 root 1.7 void
593     cfperl_init ()
594     {
595 root 1.270 extern char **environ;
596    
597     PERL_SYS_INIT3 (&settings.argc, &settings.argv, &environ);
598 root 1.32 perl = perl_alloc ();
599     perl_construct (perl);
600    
601     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
602    
603 root 1.179 const char *argv[] = {
604 root 1.198 settings.argv [0],
605 root 1.7 "-e"
606 root 1.265 "use EV; use Coro;" // required for bootstrap
607     "cf->bootstrap;" // required for datadir :*>
608 root 1.32 "unshift @INC, cf::datadir ();"
609 root 1.41 "require cf;"
610 root 1.7 };
611    
612 root 1.270 if (perl_parse (perl, xs_init, 2, (char **)argv, environ)
613 root 1.179 || perl_run (perl))
614 root 1.7 {
615     printf ("unable to initialize perl-interpreter, aborting.\n");
616     exit (EXIT_FAILURE);
617     }
618 root 1.162
619     {
620     dSP;
621    
622     PUSHMARK (SP);
623     PUTBACK;
624     call_pv ("cf::init", G_DISCARD | G_VOID);
625     }
626 root 1.7 }
627    
628 root 1.5 void cfperl_main ()
629 root 1.2 {
630     dSP;
631    
632     PUSHMARK (SP);
633     PUTBACK;
634 root 1.7 call_pv ("cf::main", G_DISCARD | G_VOID);
635     }
636    
637 root 1.109 void
638     attachable::instantiate ()
639     {
640     if (attach)
641     {
642 root 1.214 INVOKE_ATTACHABLE (INSTANTIATE, this, ARG_STRING (attach));
643 root 1.109 attach = 0;
644     }
645     }
646    
647     void
648     attachable::reattach ()
649     {
650     optimise ();
651     //TODO: check for _attachment's, very important for restarts
652 root 1.214 INVOKE_ATTACHABLE (REATTACH, this);
653 root 1.109 }
654    
655 root 1.8 static event_klass klass_of[NUM_EVENT_TYPES] = {
656     # define def(type,name) KLASS_ ## type,
657     # include "eventinc.h"
658     # undef def
659     };
660    
661 root 1.18 #define KLASS_OF(event) (((unsigned int)event) < NUM_EVENT_TYPES ? klass_of [event] : KLASS_NONE)
662    
663 root 1.8 static void
664     gather_callbacks (AV *&callbacks, AV *registry, event_type event)
665     {
666     // event must be in array
667     if (event >= 0 && event <= AvFILLp (registry))
668     {
669     SV *cbs_ = AvARRAY (registry)[event];
670    
671     // element must be list of callback entries
672     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
673     {
674     AV *cbs = (AV *)SvRV (cbs_);
675    
676     // no callback entries, no callbacks to call
677     if (AvFILLp (cbs) >= 0)
678     {
679     if (!callbacks)
680     {
681     callbacks = newAV ();
682     av_extend (callbacks, 16);
683     }
684    
685     // never use SvREFCNT_inc to copy values, but its ok here :)
686     for (int i = 0; i <= AvFILLp (cbs); ++i)
687     av_push (callbacks, SvREFCNT_inc (AvARRAY (cbs)[i]));
688     }
689     }
690     }
691     }
692    
693 root 1.109 void
694     attachable::gather_callbacks (AV *&callbacks, event_type event) const
695 root 1.6 {
696 root 1.109 ::gather_callbacks (callbacks, cb_attachable, event);
697 root 1.6
698 root 1.109 if (cb)
699     ::gather_callbacks (callbacks, cb, event);
700     }
701 root 1.8
702 root 1.109 void
703     global::gather_callbacks (AV *&callbacks, event_type event) const
704     {
705 root 1.210 ::gather_callbacks (callbacks, cb_global, event);
706 root 1.109 }
707 root 1.8
708 root 1.109 void
709     object::gather_callbacks (AV *&callbacks, event_type event) const
710     {
711 root 1.210 if (subtype && type + subtype * NUM_TYPES <= AvFILLp (cb_type))
712 root 1.109 {
713 root 1.210 SV *registry = AvARRAY (cb_type)[type + subtype * NUM_TYPES];
714 root 1.8
715 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
716     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
717     }
718 root 1.8
719 root 1.109 if (type <= AvFILLp (cb_type))
720 root 1.8 {
721 root 1.109 SV *registry = AvARRAY (cb_type)[type];
722 root 1.8
723 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
724     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
725     }
726 root 1.8
727 root 1.109 attachable::gather_callbacks (callbacks, event);
728     ::gather_callbacks (callbacks, cb_object, event);
729     }
730 root 1.8
731 root 1.109 void
732     archetype::gather_callbacks (AV *&callbacks, event_type event) const
733     {
734     attachable::gather_callbacks (callbacks, event);
735     //TODO//::gather_callbacks (callbacks, cb_archetype, event);
736     }
737 root 1.14
738 root 1.109 void
739     client::gather_callbacks (AV *&callbacks, event_type event) const
740     {
741     attachable::gather_callbacks (callbacks, event);
742     ::gather_callbacks (callbacks, cb_client, event);
743     }
744 root 1.8
745 root 1.109 void
746     player::gather_callbacks (AV *&callbacks, event_type event) const
747     {
748     attachable::gather_callbacks (callbacks, event);
749     ::gather_callbacks (callbacks, cb_player, event);
750     }
751 root 1.8
752 root 1.109 void
753     maptile::gather_callbacks (AV *&callbacks, event_type event) const
754     {
755     attachable::gather_callbacks (callbacks, event);
756     ::gather_callbacks (callbacks, cb_map, event);
757     }
758 root 1.8
759 root 1.210 void
760     _recalc_want (bitset<NUM_EVENT_TYPES> &set, AV *registry)
761     {
762     for (int event = 0; event <= AvFILLp (registry); ++event)
763     {
764     SV *cbs_ = AvARRAY (registry)[event];
765    
766     // element must be list of callback entries
767     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
768     {
769     AV *cbs = (AV *)SvRV (cbs_);
770    
771     // no callback entries, no callbacks to call
772     if (AvFILLp (cbs) >= 0)
773     set.set (event);
774     }
775     }
776     }
777    
778     // very slow and inefficient way to recalculate the global want bitsets
779     void
780     _recalc_want ()
781     {
782     ev_want_event.reset ();
783    
784     _recalc_want (ev_want_event, cb_global);
785     _recalc_want (ev_want_event, cb_attachable);
786     _recalc_want (ev_want_event, cb_object);
787     _recalc_want (ev_want_event, cb_client);
788     _recalc_want (ev_want_event, cb_player);
789     _recalc_want (ev_want_event, cb_map);
790    
791     ev_want_type.reset ();
792    
793     for (int type = 0; type <= AvFILLp (cb_type); ++type)
794     {
795     SV *cbs_ = AvARRAY (cb_type)[type];
796    
797     // element must be list of callback entries
798     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
799     {
800     AV *cbs = (AV *)SvRV (cbs_);
801    
802     // no callback entries, no callbacks to call
803     if (AvFILLp (cbs) >= 0)
804     ev_want_type.set (type % NUM_TYPES);
805     }
806     }
807     }
808    
809 root 1.109 bool
810 root 1.214 attachable::invoke (event_type event, ...)
811 root 1.109 {
812     data_type dt;
813 root 1.8
814 root 1.109 // callback call ordering should be:
815     // 1. per-object callback
816     // 2. per-class object
817     // 3. per-type callback
818     // 4. global callbacks
819 root 1.12
820 root 1.109 AV *callbacks = 0;
821     gather_callbacks (callbacks, event);
822 root 1.8
823     // short-circuit processing if no callbacks found/defined
824     if (!callbacks)
825     return 0;
826    
827 root 1.214 va_list ap;
828     va_start (ap, event);
829    
830 root 1.116 CALL_BEGIN (3);
831     CALL_ARG_SV (newSViv (event)); // only used for debugging nowadays
832     CALL_ARG_SV (newRV_noinc ((SV *)callbacks));
833 root 1.8
834 root 1.109 //TODO: unhack
835 root 1.116 if (object *op = is_a<object>(this)) CALL_ARG_SV (newSVdt (DT_OBJECT, op));
836     else if (player *pl = is_a<player>(this)) CALL_ARG_SV (newSVdt (DT_PLAYER, pl));
837     else if (client *ns = is_a<client>(this)) CALL_ARG_SV (newSVdt (DT_CLIENT, ns));
838     else if (maptile *m = is_a<maptile>(this)) CALL_ARG_SV (newSVdt (DT_MAP, m));
839 root 1.109 else if (global *gl = is_a<global>(this)) /*nop*/;
840     else
841     abort (); //TODO
842 root 1.7
843 root 1.6 for (;;)
844     {
845 root 1.8 dt = (data_type) va_arg (ap, int);
846 root 1.6
847     if (dt == DT_END)
848     break;
849 root 1.109 else if (dt == DT_AV)
850 root 1.12 {
851     AV *av = va_arg (ap, AV *);
852    
853     for (int i = 0; i <= av_len (av); ++i)
854     XPUSHs (*av_fetch (av, i, 1));
855     }
856     else
857     XPUSHs (sv_2mortal (newSVdt_va (ap, dt)));
858 root 1.6 }
859    
860     va_end (ap);
861    
862 root 1.116 CALL_CALL ("cf::do_invoke", G_SCALAR);
863 root 1.6 count = count > 0 ? POPi : 0;
864    
865 root 1.116 CALL_END;
866 root 1.6
867     return count;
868 root 1.2 }
869    
870 root 1.12 SV *
871     cfperl_result (int idx)
872     {
873 elmex 1.233 AV *av = get_av ("cf::INVOKE_RESULTS", 0);
874 root 1.12 if (!av)
875     return &PL_sv_undef;
876    
877     SV **sv = av_fetch (av, idx, 0);
878     if (!sv)
879     return &PL_sv_undef;
880    
881     return *sv;
882     }
883    
884     int
885     cfperl_result_INT (int idx)
886     {
887     return SvIV (cfperl_result (idx));
888     }
889    
890 root 1.74 double
891 root 1.73 cfperl_result_DOUBLE (int idx)
892     {
893     return SvNV (cfperl_result (idx));
894     }
895    
896 root 1.80 /////////////////////////////////////////////////////////////////////////////
897 root 1.247 // various c++ => perl glue functions
898 root 1.80
899 root 1.272 void cfperl_tick ()
900     {
901     tick_pending = 1;
902    
903     if (tick_inhibit)
904     return;
905    
906     tick_pending = 0;
907    
908     dSP;
909    
910     PUSHMARK (SP);
911     PUTBACK;
912     call_pv ("cf::tick", G_DISCARD | G_VOID);
913    
914     SvNV_set (sv_next_tick, get_next_tick ()); SvNOK_only (sv_next_tick);
915     }
916    
917 root 1.116 void
918 root 1.134 cfperl_emergency_save ()
919 root 1.116 {
920     CALL_BEGIN (0);
921 root 1.134 CALL_CALL ("cf::emergency_save", G_VOID);
922 root 1.116 CALL_END;
923     }
924    
925 root 1.165 void
926     cfperl_cleanup (int make_core)
927     {
928     CALL_BEGIN (1);
929     CALL_ARG (make_core);
930     CALL_CALL ("cf::post_cleanup", G_VOID);
931     CALL_END;
932     }
933    
934 root 1.213 void
935     cfperl_make_book (object *book, int level)
936     {
937     CALL_BEGIN (2);
938     CALL_ARG (book);
939     CALL_ARG (level);
940     CALL_CALL ("ext::books::make_book", G_VOID);
941     CALL_END;
942     }
943    
944 root 1.222 void
945     cfperl_send_msg (client *ns, int color, const char *type, const char *msg)
946     {
947     CALL_BEGIN (4);
948     CALL_ARG (ns);
949     CALL_ARG (type);
950 root 1.224 CALL_ARG_SV (newSVpv_utf8 (msg));
951 root 1.235 CALL_ARG (color);
952 root 1.222 CALL_CALL ("cf::client::send_msg", G_VOID);
953     CALL_END;
954     }
955    
956 root 1.234 int
957     cfperl_can_merge (object *ob1, object *ob2)
958     {
959     int can;
960    
961     CALL_BEGIN (2);
962     CALL_ARG (ob1);
963     CALL_ARG (ob2);
964     CALL_CALL ("cf::_can_merge", G_SCALAR);
965     can = count && SvTRUE (TOPs);
966     CALL_END;
967    
968     return can;
969     }
970    
971 root 1.244 player *
972     player::find (const char *name)
973     {
974     CALL_BEGIN (1);
975     CALL_ARG (name);
976     CALL_CALL ("cf::player::find", G_SCALAR);
977    
978     player *retval;
979    
980     if (count)
981     sv_to (POPs, retval);
982     else
983     retval = 0;
984    
985     CALL_END;
986    
987     return retval;
988     }
989    
990 root 1.116 maptile *
991 root 1.126 maptile::find_sync (const char *path, maptile *origin)
992 root 1.116 {
993     CALL_BEGIN (2);
994     CALL_ARG (path);
995     CALL_ARG (origin);
996 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
997 root 1.116
998     maptile *retval;
999    
1000     if (count)
1001     sv_to (POPs, retval);
1002     else
1003     retval = 0;
1004    
1005     CALL_END;
1006    
1007     return retval;
1008     }
1009    
1010 root 1.135 maptile *
1011 root 1.243 maptile::find_async (const char *path, maptile *origin, bool load)
1012 root 1.135 {
1013 root 1.243 CALL_BEGIN (3);
1014 root 1.135 CALL_ARG (path);
1015     CALL_ARG (origin);
1016 root 1.243 CALL_ARG (load);
1017 root 1.135 CALL_CALL ("cf::map::find_async", G_SCALAR);
1018    
1019     maptile *retval;
1020    
1021     if (count)
1022     sv_to (POPs, retval);
1023     else
1024     retval = 0;
1025    
1026     CALL_END;
1027    
1028     return retval;
1029     }
1030    
1031 root 1.116 void
1032 root 1.126 maptile::do_load_sync ()
1033     {
1034     CALL_BEGIN (1);
1035     CALL_ARG (this);
1036     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
1037     CALL_END;
1038     }
1039    
1040     void
1041 root 1.116 maptile::change_all_map_light (int change)
1042     {
1043     CALL_BEGIN (1);
1044     CALL_ARG (change);
1045     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
1046     CALL_END;
1047     }
1048    
1049     void
1050     object::enter_exit (object *exit)
1051     {
1052     if (type != PLAYER)
1053     return;
1054    
1055     CALL_BEGIN (2);
1056     CALL_ARG (this);
1057     CALL_ARG (exit);
1058     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
1059     CALL_END;
1060     }
1061    
1062 root 1.247 const char *
1063     object::ref () const
1064     {
1065     if (type == PLAYER)
1066     return format ("player/<1.%llx>/%s", (unsigned long long)uuid.seq, &name);
1067     else
1068     return 0;
1069     }
1070    
1071     object *
1072     object::deref (const char *ref)
1073     {
1074 root 1.249 object *retval = 0;
1075 root 1.247
1076 root 1.249 if (ref)
1077     {
1078     CALL_BEGIN (1);
1079     CALL_ARG (ref);
1080     CALL_CALL ("cf::object::deref", G_SCALAR);
1081    
1082     if (count)
1083     sv_to (POPs, retval);
1084 root 1.247
1085 root 1.249 CALL_END;
1086     }
1087 root 1.247
1088     return retval;
1089     }
1090    
1091 root 1.198 void
1092     log_backtrace (const char *msg)
1093     {
1094     #if HAVE_BACKTRACE
1095     void *addr [20];
1096     int size = backtrace (addr, 20);
1097    
1098     CALL_BEGIN (size);
1099     CALL_ARG (msg);
1100     for (int i = 0; i < size; ++i)
1101     CALL_ARG ((IV)addr [i]);
1102     CALL_CALL ("cf::_log_backtrace", G_VOID);
1103     CALL_END;
1104     #endif
1105     }
1106    
1107 root 1.116 /////////////////////////////////////////////////////////////////////////////
1108    
1109 root 1.265 struct EVAPI *evapi::GEVAPI;
1110     struct CoroAPI *coroapi::GCoroAPI;
1111 root 1.80
1112 root 1.189 void coroapi::do_cede_to_tick ()
1113     {
1114 root 1.272 cede_pending = 0;
1115 root 1.189 cede ();
1116     }
1117 root 1.124
1118 root 1.188 void
1119     coroapi::wait_for_tick ()
1120     {
1121     CALL_BEGIN (0);
1122     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1123     CALL_END;
1124     }
1125    
1126     void
1127     coroapi::wait_for_tick_begin ()
1128     {
1129     CALL_BEGIN (0);
1130     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1131     CALL_END;
1132     }
1133    
1134 root 1.85 void
1135 root 1.80 iow::poll (int events)
1136     {
1137 root 1.265 if (events != this->events)
1138 root 1.81 {
1139 root 1.265 int active = ev_is_active ((ev_io *)this);
1140     if (active) stop ();
1141     ev_io_set ((ev_io *)this, fd, events);
1142     if (active) start ();
1143 root 1.81 }
1144 root 1.80 }
1145    
1146 root 1.109 void
1147     _connect_to_perl ()
1148     {
1149 root 1.272 stash_cf = gv_stashpv ("cf", 1);
1150 root 1.109
1151     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1152     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1153     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1154     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1155     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1156     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1157     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1158     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1159     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1160    
1161 root 1.272 sv_now = get_sv ("cf::NOW" , 1); SvUPGRADE (sv_now , SVt_NV);
1162     sv_runtime = get_sv ("cf::RUNTIME" , 1); SvUPGRADE (sv_runtime , SVt_NV);
1163     sv_tick_start = get_sv ("cf::TICK_START", 1); SvUPGRADE (sv_tick_start, SVt_NV);
1164     sv_next_tick = get_sv ("cf::NEXT_TICK" , 1); SvUPGRADE (sv_next_tick , SVt_NV);
1165 root 1.116
1166 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1167     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1168     cb_object = get_av ("cf::CB_OBJECT", 1);
1169     cb_player = get_av ("cf::CB_PLAYER", 1);
1170     cb_client = get_av ("cf::CB_CLIENT", 1);
1171     cb_type = get_av ("cf::CB_TYPE" , 1);
1172     cb_map = get_av ("cf::CB_MAP" , 1);
1173     }
1174    
1175 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1176    
1177     BOOT:
1178     {
1179 root 1.265 I_EV_API (PACKAGE); evapi::GEVAPI = GEVAPI;
1180     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1181 root 1.80
1182 root 1.189 _connect_to_perl ();
1183    
1184 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1185 root 1.63
1186 root 1.220 //{
1187     // require_pv ("Time::HiRes");
1188     //
1189     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1190     // if (!svp) croak ("Time::HiRes is required");
1191     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1192     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1193     //}
1194 root 1.189
1195 root 1.1 static const struct {
1196     const char *name;
1197     IV iv;
1198     } *civ, const_iv[] = {
1199     # define const_iv(name) { # name, (IV)name },
1200 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1201 root 1.198 const_iv (logBacktrace)
1202 root 1.180
1203 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1204    
1205     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1206 root 1.180
1207 root 1.5 const_iv (MAX_TIME)
1208 root 1.258 const_iv (MAXSOCKBUF)
1209 root 1.189
1210 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1211     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1212     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1213     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1214     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1215     const_iv (body_wrist) const_iv (body_waist)
1216 root 1.205
1217 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1218     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1219     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1220     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1221     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1222     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1223     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1224     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1225     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1226     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1227     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1228     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1229     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1230     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1231     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1232     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1233     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1234     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1235     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1236     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1237     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1238     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1239     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1240     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1241     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1242     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1243     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1244     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1245 root 1.1
1246 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1247 root 1.14
1248 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1249     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1250 root 1.1
1251 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1252     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1253     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1254     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1255     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1256     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1257     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1258    
1259     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1260     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1261 root 1.1 const_iv (WEAP_BLUD)
1262    
1263 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1264 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1265 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1266     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1267     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1268     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1269     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1270     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1271     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1272     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1273     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1274     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1275     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1276     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1277     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1278     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1279     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1280     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1281     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1282     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1283     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1284     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1285     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1286 root 1.245 const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1287 root 1.189 const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1288     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1289    
1290     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1291     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1292     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1293     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1294 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1295 root 1.250 const_iv (NDI_NOCREATE) const_iv (NDI_CLEAR)
1296 root 1.1
1297 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1298     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1299    
1300     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1301    
1302 root 1.212 const_iv (SP_RAISE_DEAD)
1303     const_iv (SP_RUNE)
1304     const_iv (SP_MAKE_MARK)
1305     const_iv (SP_BOLT)
1306     const_iv (SP_BULLET)
1307     const_iv (SP_EXPLOSION)
1308     const_iv (SP_CONE)
1309     const_iv (SP_BOMB)
1310     const_iv (SP_WONDER)
1311     const_iv (SP_SMITE)
1312     const_iv (SP_MAGIC_MISSILE)
1313     const_iv (SP_SUMMON_GOLEM)
1314     const_iv (SP_DIMENSION_DOOR)
1315     const_iv (SP_MAGIC_MAPPING)
1316     const_iv (SP_MAGIC_WALL)
1317     const_iv (SP_DESTRUCTION)
1318     const_iv (SP_PERCEIVE_SELF)
1319     const_iv (SP_WORD_OF_RECALL)
1320     const_iv (SP_INVISIBLE)
1321     const_iv (SP_PROBE)
1322     const_iv (SP_HEALING)
1323     const_iv (SP_CREATE_FOOD)
1324     const_iv (SP_EARTH_TO_DUST)
1325     const_iv (SP_CHANGE_ABILITY)
1326     const_iv (SP_BLESS)
1327     const_iv (SP_CURSE)
1328     const_iv (SP_SUMMON_MONSTER)
1329     const_iv (SP_CHARGING)
1330     const_iv (SP_POLYMORPH)
1331     const_iv (SP_ALCHEMY)
1332     const_iv (SP_REMOVE_CURSE)
1333     const_iv (SP_IDENTIFY)
1334     const_iv (SP_DETECTION)
1335     const_iv (SP_MOOD_CHANGE)
1336     const_iv (SP_MOVING_BALL)
1337     const_iv (SP_SWARM)
1338     const_iv (SP_CHANGE_MANA)
1339     const_iv (SP_DISPEL_RUNE)
1340     const_iv (SP_CREATE_MISSILE)
1341     const_iv (SP_CONSECRATE)
1342     const_iv (SP_ANIMATE_WEAPON)
1343     const_iv (SP_LIGHT)
1344     const_iv (SP_CHANGE_MAP_LIGHT)
1345     const_iv (SP_FAERY_FIRE)
1346     const_iv (SP_CAUSE_DISEASE)
1347     const_iv (SP_AURA)
1348     const_iv (SP_TOWN_PORTAL)
1349     const_iv (SP_PARTY_SPELL)
1350    
1351 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1352     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1353 root 1.1 const_iv (F_LOCKED)
1354    
1355 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1356    
1357     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1358     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1359    
1360     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1361    
1362     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1363 root 1.258 const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR)
1364 root 1.189
1365     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1366     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1367    
1368     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1369    
1370     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1371     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1372     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1373     const_iv (M_ICE) const_iv (M_SPECIAL)
1374    
1375     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1376     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1377    
1378     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1379     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1380     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1381     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1382     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1383     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1384     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1385     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1386     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1387     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1388 root 1.1 const_iv (SK_POISON_NAIL)
1389    
1390 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1391     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1392     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1393     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1394     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1395     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1396    
1397     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1398    
1399     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1400     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1401     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1402     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1403     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1404     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1405     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1406    
1407 root 1.276 const_iv (MAP_ACTIVE) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1408     const_iv (MAP_INACTIVE)
1409 root 1.189
1410     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1411     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1412    
1413 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1414    
1415 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1416    
1417     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1418 root 1.99
1419 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1420 root 1.117
1421     // random map generator
1422 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1423     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1424    
1425     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1426     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1427     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1428    
1429     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1430     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1431 root 1.195
1432     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1433     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1434     const_iv (GT_MINIMAL)
1435 root 1.238
1436     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1437     const_iv (FT_RSRC) const_iv (FT_NUM)
1438 root 1.1 };
1439    
1440     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1441 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1442 root 1.1
1443     static const struct {
1444     const char *name;
1445 root 1.14 int skip;
1446 root 1.7 IV klass;
1447 root 1.1 IV iv;
1448 root 1.6 } *eiv, event_iv[] = {
1449 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1450 root 1.6 # include "eventinc.h"
1451     # undef def
1452     };
1453    
1454     AV *av = get_av ("cf::EVENT", 1);
1455    
1456     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1457 root 1.7 {
1458     AV *event = newAV ();
1459 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1460 root 1.7 av_push (event, newSViv (eiv->klass));
1461     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1462 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1463 root 1.7 }
1464 root 1.14 }
1465    
1466 root 1.109 void _connect_to_perl ()
1467 root 1.14
1468 root 1.210 void _recalc_want ()
1469    
1470 root 1.47 void _global_reattach ()
1471 root 1.14 CODE:
1472     {
1473     // reattach to all attachable objects in the game.
1474 root 1.128 for_all_clients (ns)
1475     ns->reattach ();
1476 root 1.96
1477 root 1.128 for_all_objects (op)
1478 root 1.109 op->reattach ();
1479 root 1.1 }
1480    
1481 root 1.192 # support function for map-world.ext
1482     void _quantise (SV *data_sv, SV *plt_sv)
1483     CODE:
1484     {
1485     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1486     croak ("_quantise called with invalid agruments");
1487    
1488     plt_sv = SvRV (plt_sv);
1489     SV **plt = AvARRAY (plt_sv);
1490     int plt_count = AvFILL (plt_sv) + 1;
1491    
1492     STRLEN len;
1493     char *data = SvPVbyte (data_sv, len);
1494     char *dst = data;
1495    
1496     while (len >= 3)
1497     {
1498     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1499     {
1500     char *val = SvPVX (*val_sv);
1501    
1502     if (val [0] == data [0]
1503     && val [1] == data [1]
1504     && val [2] == data [2])
1505     {
1506     *dst++ = val [3];
1507     goto next;
1508     }
1509     }
1510    
1511     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1512     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1513     dst - SvPVX (data_sv), len);
1514    
1515     next:
1516     data += 3;
1517     len -= 3;
1518     }
1519    
1520     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1521     }
1522    
1523 root 1.273 void evthread_start (int aiofd)
1524 root 1.272
1525     void cede_to_tick ()
1526 root 1.236 CODE:
1527 root 1.272 coroapi::cede_to_tick ();
1528 root 1.236
1529 root 1.272 NV till_tick ()
1530 root 1.236 CODE:
1531 root 1.272 RETVAL = SvNVX (sv_next_tick) - now ();
1532 root 1.236 OUTPUT:
1533     RETVAL
1534    
1535 root 1.272 int tick_inhibit ()
1536 root 1.236 CODE:
1537 root 1.272 RETVAL = tick_inhibit;
1538 root 1.236 OUTPUT:
1539     RETVAL
1540    
1541 root 1.272 void tick_inhibit_inc ()
1542     CODE:
1543     ++tick_inhibit;
1544    
1545     void tick_inhibit_dec ()
1546     CODE:
1547     if (!--tick_inhibit)
1548     if (tick_pending)
1549     {
1550     ev_async_send (EV_DEFAULT, &tick_watcher);
1551     coroapi::cede ();
1552     }
1553    
1554     void server_tick ()
1555     CODE:
1556     {
1557     NOW = ev_now (EV_DEFAULT);
1558     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1559     SvNV_set (sv_tick_start, NOW); SvNOK_only (sv_tick_start);
1560     runtime = SvNVX (sv_runtime);
1561    
1562     server_tick ();
1563    
1564     NOW = ev_time ();
1565     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1566     runtime += TICK;
1567     SvNV_set (sv_runtime, runtime); SvNOK_only (sv_runtime);
1568     }
1569    
1570 root 1.1 NV floor (NV x)
1571    
1572     NV ceil (NV x)
1573    
1574 root 1.143 NV rndm (...)
1575     CODE:
1576     switch (items)
1577     {
1578     case 0: RETVAL = rndm (); break;
1579     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1580     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1581     default: croak ("cf::rndm requires none, one or two parameters."); break;
1582     }
1583     OUTPUT:
1584     RETVAL
1585    
1586 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1587     CODE:
1588     RETVAL = clamp (value, min_value, max_value);
1589     OUTPUT:
1590     RETVAL
1591    
1592     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1593     CODE:
1594     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1595     OUTPUT:
1596     RETVAL
1597    
1598 root 1.268 void weaken (...)
1599     PROTOTYPE: @
1600     CODE:
1601     while (items > 0)
1602     sv_rvweaken (ST (--items));
1603    
1604 root 1.1 void
1605 root 1.198 log_backtrace (utf8_string msg)
1606    
1607     void
1608     LOG (int flags, utf8_string msg)
1609 root 1.1 PROTOTYPE: $$
1610 root 1.198 C_ARGS: flags, "%s", msg
1611 root 1.1
1612 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1613 root 1.1 PROTOTYPE: $$
1614    
1615 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1616 root 1.1 PROTOTYPE: $$
1617    
1618     void
1619 root 1.259 mallinfo ()
1620     PPCODE:
1621     {
1622     #if __GLIBC__
1623     struct mallinfo mai = mallinfo ();
1624 root 1.260 EXTEND (SP, 10*2);
1625 root 1.259 PUSHs (sv_2mortal (newSVpv ("arena" , 0))); PUSHs (sv_2mortal (newSViv (mai.arena)));
1626     PUSHs (sv_2mortal (newSVpv ("ordblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.ordblks)));
1627 root 1.260 PUSHs (sv_2mortal (newSVpv ("smblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.smblks)));
1628 root 1.259 PUSHs (sv_2mortal (newSVpv ("hblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblks)));
1629     PUSHs (sv_2mortal (newSVpv ("hblkhd" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblkhd)));
1630 root 1.260 PUSHs (sv_2mortal (newSVpv ("usmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.usmblks)));
1631     PUSHs (sv_2mortal (newSVpv ("fsmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.fsmblks)));
1632 root 1.259 PUSHs (sv_2mortal (newSVpv ("uordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.uordblks)));
1633     PUSHs (sv_2mortal (newSVpv ("fordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.fordblks)));
1634     PUSHs (sv_2mortal (newSVpv ("keepcost", 0))); PUSHs (sv_2mortal (newSViv (mai.keepcost)));
1635     #endif
1636 root 1.261 EXTEND (SP, 2*2);
1637     PUSHs (sv_2mortal (newSVpv ("slice_alloc", 0))); PUSHs (sv_2mortal (newSVuv (slice_alloc)));
1638     PUSHs (sv_2mortal (newSVpv ("shstr_alloc", 0))); PUSHs (sv_2mortal (newSVuv (shstr_alloc)));
1639 root 1.259 }
1640    
1641     void
1642 root 1.1 sub_generation_inc ()
1643     CODE:
1644     PL_sub_generation++;
1645    
1646 root 1.183 const_octet_string
1647 root 1.1 mapdir ()
1648     PROTOTYPE:
1649     ALIAS:
1650     mapdir = 0
1651     uniquedir = 1
1652     tmpdir = 2
1653     confdir = 3
1654     localdir = 4
1655     playerdir = 5
1656     datadir = 6
1657     CODE:
1658 root 1.19 switch (ix)
1659     {
1660     case 0: RETVAL = settings.mapdir ; break;
1661     case 1: RETVAL = settings.uniquedir; break;
1662     case 2: RETVAL = settings.tmpdir ; break;
1663     case 3: RETVAL = settings.confdir ; break;
1664     case 4: RETVAL = settings.localdir ; break;
1665     case 5: RETVAL = settings.playerdir; break;
1666     case 6: RETVAL = settings.datadir ; break;
1667     }
1668 root 1.1 OUTPUT: RETVAL
1669    
1670 root 1.120 void abort ()
1671    
1672 root 1.199 void reset_signals ()
1673    
1674 root 1.270 void fork_abort (const_octet_string cause = "cf::fork_abort")
1675 root 1.144
1676 root 1.270 void cleanup (const_octet_string cause, bool make_core = false)
1677 root 1.134
1678 root 1.116 void emergency_save ()
1679    
1680 root 1.156 void _exit (int status = EXIT_SUCCESS)
1681    
1682 root 1.125 #if _POSIX_MEMLOCK
1683    
1684     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1685 root 1.271 INIT:
1686 root 1.277 #ifdef __linux
1687 root 1.271 mallopt (M_PERTURB, 0xaa); // bug-workaround for linux glibc+mlockall+calloc
1688 root 1.277 #endif
1689 root 1.125
1690     int munlockall ()
1691    
1692     #endif
1693    
1694 root 1.183 int find_animation (utf8_string text)
1695 root 1.1 PROTOTYPE: $
1696    
1697 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1698 root 1.1
1699 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1700 root 1.1
1701     int
1702     exp_to_level (val64 exp)
1703     CODE:
1704     {
1705     int i = 0;
1706    
1707     RETVAL = settings.max_level;
1708    
1709     for (i = 1; i <= settings.max_level; i++)
1710     {
1711     if (levels[i] > exp)
1712     {
1713     RETVAL = i - 1;
1714     break;
1715     }
1716     }
1717     }
1718     OUTPUT: RETVAL
1719    
1720     val64
1721     level_to_min_exp (int level)
1722     CODE:
1723     if (level > settings.max_level)
1724     RETVAL = levels[settings.max_level];
1725     else if (level < 1)
1726     RETVAL = 0;
1727     else
1728     RETVAL = levels[level];
1729     OUTPUT: RETVAL
1730    
1731     SV *
1732     resistance_to_string (int atnr)
1733     CODE:
1734     if (atnr >= 0 && atnr < NROFATTACKS)
1735     RETVAL = newSVpv (resist_plus[atnr], 0);
1736     else
1737     XSRETURN_UNDEF;
1738     OUTPUT: RETVAL
1739    
1740 root 1.275 UUID
1741 root 1.274 uuid_cur ()
1742     CODE:
1743 root 1.275 RETVAL = UUID::cur;
1744 root 1.274 OUTPUT:
1745     RETVAL
1746    
1747 root 1.275 UUID
1748 root 1.274 uuid_gen ()
1749     CODE:
1750 root 1.275 RETVAL = UUID::gen ();
1751     OUTPUT:
1752     RETVAL
1753    
1754     val64
1755     uuid_seq (UUID uuid)
1756     CODE:
1757     RETVAL = uuid.seq;
1758     OUTPUT:
1759     RETVAL
1760    
1761     UUID
1762     uuid_str (val64 seq)
1763     CODE:
1764     RETVAL.seq = seq;
1765 root 1.274 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.278 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