ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.282
Committed: Wed Apr 23 07:13:23 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-2_52
Changes since 1.281: +1 -0 lines
Log Message:
do less full floorbox updates, just send/delete item

File Contents

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