ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.242
Committed: Mon Aug 6 10:54:12 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.241: +1 -1 lines
Log Message:
rather uncertain optimisation.. trying to take advantage of cmov instructions
if refptr.

a = b before:

     510:       48 8b 16                mov    (%rsi),%rdx
     513:       48 85 d2                test   %rdx,%rdx
     516:       75 0c                   jne    524 <xyzzy(refptr<object>, refptr<object>)+0x14>
     518:       48 8b 07                mov    (%rdi),%rax
     51b:       48 85 c0                test   %rax,%rax
     51e:       75 09                   jne    529 <xyzzy(refptr<object>, refptr<object>)+0x19>
     520:       48 89 17                mov    %rdx,(%rdi)
     523:       c3                      retq
     524:       ff 42 08                incl   0x8(%rdx)
     527:       eb ef                   jmp    518 <xyzzy(refptr<object>, refptr<object>)+0x8>
     529:       ff 48 08                decl   0x8(%rax)
     52c:       0f 1f 40 00             nopl   0x0(%rax)
     530:       eb ee                   jmp    520 <xyzzy(refptr<object>, refptr<object>)+0x10>

a = b after:

     141:       4c 8b 0f                mov    (%rdi),%r9
     144:       ba 00 00 00 00          mov    $0x0,%edx
     149:       4d 8d 41 08             lea    0x8(%r9),%r8
     14d:       4d 85 c9                test   %r9,%r9
     150:       4c 0f 44 c2             cmove  %rdx,%r8
     154:       41 ff 08                decl   (%r8)
     157:       48 8b 06                mov    (%rsi),%rax
     15a:       48 8d 48 08             lea    0x8(%rax),%rcx
     15e:       48 85 c0                test   %rax,%rax
     161:       48 89 07                mov    %rax,(%rdi)
     164:       48 0f 45 d1             cmovne %rcx,%rdx
     168:       ff 02                   incl   (%rdx)
     16a:       c3                      retq

note no jumps but larger codeside (1.7kb net increase).

File Contents

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