ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.255
Committed: Tue Sep 11 15:33:35 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.254: +25 -0 lines
Log Message:
first tag target support, goto *tag and slaying *tag should now work

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.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2156    
2157     player *player (object *op)
2158     CODE:
2159     RETVAL = op->contr;
2160     OUTPUT: RETVAL
2161    
2162 root 1.105 void check_score (object *op)
2163    
2164 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2165 root 1.120 CODE:
2166     new_draw_info (flags, 0, op, txt);
2167 root 1.1
2168     void kill_player (object *op)
2169    
2170 root 1.58 void esrv_update_item (object *op, int what, object *item)
2171     C_ARGS: what, op, item
2172    
2173 root 1.183 int command_summon (object *op, utf8_string params)
2174 root 1.67
2175 root 1.183 int command_arrest (object *op, utf8_string params)
2176 root 1.67
2177 root 1.66
2178 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2179 root 1.1
2180 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2181 root 1.62
2182 root 1.18 int invoke (player *pl, int event, ...)
2183     CODE:
2184     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2185 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2186     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2187 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2188 root 1.18 OUTPUT: RETVAL
2189    
2190 root 1.12 SV *registry (player *pl)
2191 root 1.1
2192 root 1.102 void
2193     save_stats (player *pl)
2194     CODE:
2195     pl->ob->stats.hp = pl->ob->stats.maxhp;
2196     pl->ob->stats.sp = pl->ob->stats.maxsp;
2197     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2198     pl->orig_stats = pl->ob->stats;
2199    
2200 root 1.217 void clear_los (player *pl)
2201    
2202 root 1.1 void cf_player_move (player *pl, int dir)
2203    
2204     bool
2205     cell_visible (player *pl, int dx, int dy)
2206     CODE:
2207 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2208     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2209 root 1.1 OUTPUT:
2210     RETVAL
2211    
2212 root 1.4 void
2213 root 1.1 send (player *pl, SV *packet)
2214     CODE:
2215     {
2216     STRLEN len;
2217     char *buf = SvPVbyte (packet, len);
2218    
2219 root 1.100 if (pl->ns)
2220     pl->ns->send_packet (buf, len);
2221 root 1.1 }
2222    
2223     int
2224     listening (player *pl, int new_value = -1)
2225     CODE:
2226     RETVAL = pl->listening;
2227     if (new_value >= 0)
2228     pl->listening = new_value;
2229     OUTPUT:
2230     RETVAL
2231    
2232 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2233 root 1.45 PROTOTYPE: $;$$$
2234 root 1.1 PPCODE:
2235 root 1.45 if (GIMME_V != G_VOID)
2236     {
2237     EXTEND (SP, 3);
2238     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2239     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2240     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2241     }
2242 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2243     if (x) sv_to (x, pl->bed_x);
2244     if (y) sv_to (y, pl->bed_y);
2245 root 1.1
2246     void
2247     list ()
2248     PPCODE:
2249 root 1.128 for_all_players (pl)
2250 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2251 root 1.1
2252    
2253     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2254    
2255 root 1.61 int invoke (maptile *map, int event, ...)
2256 root 1.18 CODE:
2257     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2258 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2259     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2260 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2261 root 1.25 OUTPUT: RETVAL
2262 root 1.18
2263 root 1.61 SV *registry (maptile *map)
2264 root 1.12
2265 root 1.255 void
2266     find_tagged_objects (maptile *map, utf8_string tag = 0)
2267     PPCODE:
2268     {
2269     if (!map->spaces)
2270     XSRETURN_EMPTY;
2271    
2272     if (tag)
2273     {
2274     shstr_cmp tag_ (tag);
2275    
2276     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2277     for (object *op = ms->bot; op; op = op->above)
2278     if (op->tag == tag_)
2279     XPUSHs (sv_2mortal (to_sv (op)));
2280     }
2281     else
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)
2286     XPUSHs (sv_2mortal (to_sv (op)));
2287     }
2288     }
2289    
2290 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2291 root 1.1
2292 root 1.116 void
2293     maptile::instantiate ()
2294    
2295     maptile *new ()
2296 root 1.1 PROTOTYPE:
2297     CODE:
2298 root 1.116 RETVAL = new maptile;
2299 root 1.1 OUTPUT:
2300     RETVAL
2301    
2302 root 1.116 void
2303 root 1.117 maptile::players ()
2304     PPCODE:
2305     if (GIMME_V == G_SCALAR)
2306 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2307 root 1.117 else if (GIMME_V == G_ARRAY)
2308     {
2309     EXTEND (SP, THIS->players);
2310     for_all_players (pl)
2311     if (pl->ob && pl->ob->map == THIS)
2312 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2313 root 1.117 }
2314    
2315 root 1.156 void
2316 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2317 root 1.156 CODE:
2318     {
2319 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2320     croak ("maptile::add_underlay: palette must be arrayref");
2321 root 1.156
2322 root 1.168 palette = SvRV (palette);
2323 root 1.156
2324 root 1.168 STRLEN idxlen;
2325     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2326 root 1.156
2327 root 1.168 for (int x = 0; x < THIS->width; ++x)
2328     for (int y = 0; y < THIS->height; ++y)
2329     {
2330     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2331     if (op->flag [FLAG_IS_FLOOR])
2332     goto skip_space;
2333    
2334     {
2335     int offs = offset + y * stride + x;
2336     if (IN_RANGE_EXC (offs, 0, idxlen))
2337     {
2338     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2339     {
2340     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2341     ob->flag [FLAG_NO_MAP_SAVE] = true;
2342     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2343 root 1.200
2344     if (ob->randomitems)
2345     {
2346 root 1.203 if (!ob->above)
2347     {
2348     ob->create_treasure (ob->randomitems);
2349    
2350     for (object *op = ob->above; op; op = op->above)
2351     op->flag [FLAG_NO_MAP_SAVE] = true;
2352     }
2353    
2354 root 1.200 ob->randomitems = 0;
2355     }
2356 root 1.168 }
2357     }
2358     }
2359 root 1.156
2360 root 1.168 skip_space: ;
2361     }
2362     }
2363    
2364     void
2365     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2366     CODE:
2367     {
2368     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2369     croak ("maptile::set_regiondata: palette must be arrayref");
2370    
2371     palette = SvRV (palette);
2372    
2373     STRLEN idxlen;
2374     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2375    
2376 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2377 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2378    
2379     for (int i = av_len ((AV *)palette) + 1; i--; )
2380 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2381 root 1.168
2382     for (int y = 0; y < THIS->height; ++y)
2383     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2384    
2385     sfree (THIS->regions, THIS->size ());
2386 root 1.230 delete [] THIS->regionmap;
2387 root 1.168
2388     THIS->regions = regions;
2389 root 1.156 THIS->regionmap = regionmap;
2390     }
2391    
2392 root 1.193 void
2393     maptile::create_region_treasure ()
2394     CODE:
2395     {
2396     object *op = object::create ();
2397     op->type = FLOOR;
2398     op->map = THIS;
2399    
2400     for (int x = 0; x < THIS->width; ++x)
2401     for (int y = 0; y < THIS->height; ++y)
2402     {
2403     region *rgn = THIS->region (x, y);
2404    
2405     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2406     if (rgn->treasure && rndm () < rgn->treasure_density)
2407     {
2408     op->x = x;
2409     op->y = y;
2410     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2411     }
2412     }
2413    
2414     op->destroy ();
2415     }
2416    
2417 root 1.74 int out_of_map (maptile *map, int x, int y)
2418    
2419 root 1.29 void
2420 root 1.61 trigger (maptile *map, long connection, bool state = true)
2421 root 1.29 CODE:
2422     activate_connection (map, connection, state);
2423    
2424     void
2425 root 1.61 get_connection (maptile *map, long connection)
2426 root 1.29 PPCODE:
2427     oblinkpt *obp = get_connection_links (map, connection);
2428     if (obp)
2429     for (objectlink *ol = obp->link; ol; ol = ol->next)
2430 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2431 root 1.29
2432 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2433 root 1.1
2434 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2435 root 1.1
2436 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2437 root 1.1 C_ARGS: str, map, nx, ny
2438    
2439     void
2440 root 1.140 get_map_flags (maptile *map, int x, int y)
2441 root 1.1 PPCODE:
2442     {
2443 root 1.61 maptile *nmap = 0;
2444 root 1.1 I16 nx = 0, ny = 0;
2445 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2446 root 1.1
2447     EXTEND (SP, 4);
2448     PUSHs (sv_2mortal (newSViv (flags)));
2449    
2450     if (GIMME_V == G_ARRAY)
2451     {
2452     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2453     PUSHs (sv_2mortal (newSViv (nx)));
2454     PUSHs (sv_2mortal (newSViv (ny)));
2455     }
2456     }
2457    
2458     void
2459 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2460 root 1.1 PROTOTYPE: $$$
2461     PPCODE:
2462     {
2463     object *o;
2464 root 1.61 maptile *nmap = 0;
2465 root 1.1 I16 nx, ny;
2466    
2467 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2468 root 1.1
2469     if (nmap)
2470     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2471     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2472     }
2473    
2474     SV *
2475 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2476 root 1.1 PROTOTYPE: $$$
2477     ALIAS:
2478     top_at = 1
2479     flags_at = 2
2480     light_at = 3
2481     move_block_at = 4
2482     move_slow_at = 5
2483     move_on_at = 6
2484     move_off_at = 7
2485     INIT:
2486 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2487 root 1.1 CODE:
2488     switch (ix)
2489     {
2490     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2491     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2492     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2493     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2494     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2495     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2496     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2497     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2498     }
2499 root 1.122 OUTPUT: RETVAL
2500 root 1.1
2501 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2502    
2503     void fix_walls_around (maptile *map, int x, int y)
2504 root 1.1
2505 root 1.117 # worst xs function of my life
2506 root 1.140 bool
2507 root 1.117 _create_random_map (\
2508 root 1.140 maptile *self,\
2509 root 1.183 utf8_string wallstyle,\
2510     utf8_string wall_name,\
2511     utf8_string floorstyle,\
2512     utf8_string monsterstyle,\
2513     utf8_string treasurestyle,\
2514     utf8_string layoutstyle,\
2515     utf8_string doorstyle,\
2516     utf8_string decorstyle,\
2517     utf8_string origin_map,\
2518     utf8_string final_map,\
2519     utf8_string exitstyle,\
2520     utf8_string this_map,\
2521     utf8_string exit_on_final_map,\
2522 root 1.146 int xsize,\
2523     int ysize,\
2524 root 1.117 int expand2x,\
2525     int layoutoptions1,\
2526     int layoutoptions2,\
2527     int layoutoptions3,\
2528     int symmetry,\
2529     int difficulty,\
2530     int difficulty_given,\
2531     float difficulty_increase,\
2532     int dungeon_level,\
2533     int dungeon_depth,\
2534     int decoroptions,\
2535     int orientation,\
2536     int origin_y,\
2537     int origin_x,\
2538 root 1.146 U32 random_seed,\
2539 root 1.117 val64 total_map_hp,\
2540     int map_layout_style,\
2541     int treasureoptions,\
2542     int symmetry_used,\
2543 root 1.137 region *region,\
2544 root 1.183 utf8_string custom\
2545 root 1.117 )
2546     CODE:
2547     {
2548     random_map_params rmp;
2549    
2550     assign (rmp.wallstyle , wallstyle);
2551     assign (rmp.wall_name , wall_name);
2552     assign (rmp.floorstyle , floorstyle);
2553     assign (rmp.monsterstyle , monsterstyle);
2554     assign (rmp.treasurestyle , treasurestyle);
2555     assign (rmp.layoutstyle , layoutstyle);
2556     assign (rmp.doorstyle , doorstyle);
2557     assign (rmp.decorstyle , decorstyle);
2558     assign (rmp.exitstyle , exitstyle);
2559     assign (rmp.exit_on_final_map, exit_on_final_map);
2560    
2561 root 1.122 rmp.origin_map = origin_map;
2562     rmp.final_map = final_map;
2563     rmp.this_map = this_map;
2564 root 1.146 rmp.xsize = xsize;
2565     rmp.ysize = ysize;
2566 root 1.117 rmp.expand2x = expand2x;
2567     rmp.layoutoptions1 = layoutoptions1;
2568     rmp.layoutoptions2 = layoutoptions2;
2569     rmp.layoutoptions3 = layoutoptions3;
2570     rmp.symmetry = symmetry;
2571     rmp.difficulty = difficulty;
2572     rmp.difficulty_given = difficulty_given;
2573     rmp.difficulty_increase = difficulty_increase;
2574     rmp.dungeon_level = dungeon_level;
2575     rmp.dungeon_depth = dungeon_depth;
2576     rmp.decoroptions = decoroptions;
2577     rmp.orientation = orientation;
2578     rmp.origin_y = origin_y;
2579     rmp.origin_x = origin_x;
2580     rmp.random_seed = random_seed;
2581 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2582 root 1.117 rmp.map_layout_style = map_layout_style;
2583     rmp.treasureoptions = treasureoptions;
2584     rmp.symmetry_used = symmetry_used;
2585     rmp.region = region;
2586 root 1.137 rmp.custom = custom;
2587 root 1.117
2588 root 1.140 RETVAL = self->generate_random_map (&rmp);
2589 root 1.117 }
2590     OUTPUT:
2591     RETVAL
2592    
2593 root 1.19 MODULE = cf PACKAGE = cf::arch
2594 root 1.1
2595 root 1.218 int archetypes_size ()
2596     CODE:
2597     RETVAL = archetypes.size ();
2598     OUTPUT: RETVAL
2599    
2600     archetype *archetypes (U32 index)
2601     CODE:
2602     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2603     OUTPUT: RETVAL
2604 root 1.1
2605 root 1.212 object *instantiate (archetype *arch)
2606     CODE:
2607     RETVAL = arch_to_object (arch);
2608     OUTPUT:
2609     RETVAL
2610    
2611 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2612 root 1.1
2613 root 1.19 MODULE = cf PACKAGE = cf::party
2614 root 1.1
2615 root 1.19 partylist *first ()
2616 root 1.1 PROTOTYPE:
2617 root 1.19 CODE:
2618     RETVAL = get_firstparty ();
2619     OUTPUT: RETVAL
2620 root 1.1
2621 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2622 root 1.1
2623 root 1.19 MODULE = cf PACKAGE = cf::region
2624 root 1.1
2625 root 1.161 void
2626     list ()
2627     PPCODE:
2628     for_all_regions (rgn)
2629     XPUSHs (sv_2mortal (to_sv (rgn)));
2630    
2631 root 1.183 region *find (utf8_string name)
2632 root 1.161 PROTOTYPE: $
2633 root 1.19 CODE:
2634 root 1.161 RETVAL = region::find (name);
2635 root 1.19 OUTPUT: RETVAL
2636 root 1.1
2637 root 1.183 region *find_fuzzy (utf8_string name)
2638 root 1.122 PROTOTYPE: $
2639     CODE:
2640 root 1.161 RETVAL = region::find_fuzzy (name);
2641 root 1.122 OUTPUT: RETVAL
2642    
2643 root 1.186 int specificity (region *rgn)
2644     CODE:
2645     RETVAL = 0;
2646     while (rgn = rgn->parent)
2647     RETVAL++;
2648     OUTPUT: RETVAL
2649    
2650 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2651 root 1.1
2652 root 1.19 MODULE = cf PACKAGE = cf::living
2653 root 1.1
2654 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2655 root 1.1
2656 root 1.76 MODULE = cf PACKAGE = cf::settings
2657    
2658 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2659 root 1.76
2660 root 1.84 MODULE = cf PACKAGE = cf::client
2661 root 1.79
2662 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2663 root 1.79
2664 root 1.84 int invoke (client *ns, int event, ...)
2665 root 1.79 CODE:
2666 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2667 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2668     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2669 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2670 root 1.79 OUTPUT: RETVAL
2671    
2672 root 1.84 SV *registry (client *ns)
2673 root 1.79
2674 root 1.100 void
2675     list ()
2676     PPCODE:
2677     EXTEND (SP, clients.size ());
2678     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2679     PUSHs (sv_2mortal (to_sv (*i)));
2680    
2681 root 1.88 void
2682 root 1.100 client::send_packet (SV *packet)
2683     CODE:
2684     {
2685     STRLEN len;
2686     char *buf = SvPVbyte (packet, len);
2687    
2688     THIS->send_packet (buf, len);
2689     }
2690    
2691 root 1.237 faceidx
2692 root 1.238 client::need_face (utf8_string name, int pri = 0)
2693 root 1.237 CODE:
2694 root 1.238 RETVAL = face_find (name, 0);
2695     if (RETVAL)
2696     {
2697     THIS->send_face (RETVAL, pri);
2698     THIS->flush_fx ();
2699     }
2700     OUTPUT:
2701     RETVAL
2702    
2703     int
2704     client::fx_want (int idx, int value = -1)
2705     CODE:
2706     if (0 < idx && idx < FT_NUM)
2707     {
2708     RETVAL = THIS->fx_want [idx];
2709     if (items > 2)
2710     THIS->fx_want [idx] = value;
2711     }
2712     else
2713     RETVAL = 0;
2714 root 1.237 OUTPUT:
2715     RETVAL
2716    
2717 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2718    
2719     faceidx sound_find (utf8_string name)
2720    
2721 root 1.240 void sound_set (utf8_string str, faceidx face)
2722    
2723     # dire hack
2724     void old_sound_index (int idx, faceidx face)
2725     CODE:
2726     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2727     old_sound_index [idx] = face;
2728    
2729 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2730    
2731 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2732 root 1.176
2733 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2734 root 1.176
2735 root 1.183 faceidx alloc (utf8_string name)
2736 root 1.176 CODE:
2737     {
2738     do
2739     {
2740     RETVAL = faces.size ();
2741 root 1.177 faces.resize (RETVAL + 1);
2742 root 1.176 }
2743     while (!RETVAL); // crude way to leave index 0
2744    
2745     faces [RETVAL].name = name;
2746     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2747    
2748     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2749     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2750     }
2751     OUTPUT: RETVAL
2752    
2753 root 1.227 void set_type (faceidx idx, int value)
2754     ALIAS:
2755     set_type = 0
2756     set_visibility = 1
2757     set_magicmap = 2
2758     set_smooth = 3
2759     set_smoothlevel = 4
2760 root 1.176 CODE:
2761 root 1.229 faceinfo *f = face_info (idx); assert (f);
2762 root 1.227 switch (ix)
2763     {
2764     case 0: f->type = value; break;
2765     case 1: f->visibility = value; break;
2766     case 2: f->magicmap = value; break;
2767     case 3: f->smooth = value; break;
2768     case 4: f->smoothlevel = value; break;
2769     }
2770 root 1.177
2771     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2772 root 1.176 CODE:
2773 root 1.182 {
2774 root 1.231 faceinfo *f = face_info (idx); assert (f);
2775     facedata *d = &(faceset ? f->data64 : f->data32);
2776 root 1.181 sv_to (data, d->data);
2777     STRLEN clen;
2778     char *cdata = SvPVbyte (chksum, clen);
2779 root 1.182 clen = min (CHKSUM_SIZE, clen);
2780    
2781     if (memcmp (d->chksum, cdata, clen))
2782     {
2783     memcpy (d->chksum, cdata, clen);
2784    
2785     // invalidate existing client face info
2786     for_all_clients (ns)
2787     if (ns->faceset == faceset)
2788     {
2789     ns->faces_sent [idx] = false;
2790     ns->force_newmap = true;
2791     }
2792     }
2793     }
2794 root 1.176
2795 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2796     CODE:
2797     facedata *d = face_data (idx, faceset); assert (d);
2798     RETVAL = d->data.size ();
2799     OUTPUT:
2800     RETVAL
2801    
2802     SV *get_chksum (faceidx idx, int faceset = 0)
2803     CODE:
2804     facedata *d = face_data (idx, faceset); assert (d);
2805     RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2806     OUTPUT:
2807     RETVAL
2808    
2809 root 1.177 void invalidate (faceidx idx)
2810     CODE:
2811     for_all_clients (ns)
2812 root 1.182 {
2813     ns->faces_sent [idx] = false;
2814     ns->force_newmap = true;
2815     }
2816 root 1.177
2817     void invalidate_all ()
2818     CODE:
2819     for_all_clients (ns)
2820 root 1.182 {
2821     ns->faces_sent.reset ();
2822     ns->force_newmap = true;
2823     }
2824 root 1.177
2825 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2826    
2827     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2828    
2829     animidx anim_find (utf8_string name)
2830     CODE:
2831     RETVAL = animation::find (name).number;
2832     OUTPUT: RETVAL
2833    
2834     animidx set (utf8_string name, SV *frames, int facings = 1)
2835     CODE:
2836     {
2837     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2838     croak ("frames must be an arrayref");
2839    
2840     AV *av = (AV *)SvRV (frames);
2841    
2842     animation *anim = &animation::find (name);
2843     if (anim->number)
2844     {
2845     anim->resize (av_len (av) + 1);
2846     anim->facings = facings;
2847     }
2848     else
2849     anim = &animation::create (name, av_len (av) + 1, facings);
2850    
2851     for (int i = 0; i < anim->num_animations; ++i)
2852     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2853     }
2854     OUTPUT: RETVAL
2855    
2856     void invalidate_all ()
2857     CODE:
2858     for_all_clients (ns)
2859     ns->anims_sent.reset ();
2860    
2861 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2862    
2863     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2864    
2865     SV *
2866     new (char *klass)
2867     CODE:
2868     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2869     OUTPUT: RETVAL
2870    
2871     void
2872     DESTROY (SV *sv)
2873     CODE:
2874     object_freezer *self;
2875     sv_to (sv, self);
2876     delete self;
2877    
2878     MODULE = cf PACKAGE = cf::object::thawer
2879    
2880     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2881    
2882     SV *
2883     new_from_file (char *klass, octet_string path)
2884     CODE:
2885     object_thawer *f = new object_thawer (path);
2886     if (!*f)
2887     {
2888     delete f;
2889     XSRETURN_UNDEF;
2890     }
2891     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2892     OUTPUT: RETVAL
2893    
2894     void
2895     DESTROY (SV *sv)
2896     CODE:
2897     object_thawer *self;
2898     sv_to (sv, self);
2899     delete self;
2900    
2901 root 1.252 void
2902 root 1.253 extract_tags (object_thawer *self)
2903 root 1.254 PPCODE:
2904 root 1.252 while (self->kw != KW_EOF)
2905     {
2906 root 1.254 PUTBACK;
2907 root 1.253 coroapi::cede_to_tick_every (5000);
2908 root 1.254 SPAGAIN;
2909 root 1.253
2910 root 1.252 if (self->kw == KW_tag)
2911 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
2912 root 1.252
2913     self->skip ();
2914     }
2915