ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.256
Committed: Wed Sep 12 11:10:11 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.255: +7 -0 lines
Log Message:
- rewrite/cleanup ob_blocked a little. its more efficient now, probably
  has less bugs and more bugs.
- get rid of now unused P_NO_PASS.

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