ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.252
Committed: Mon Sep 10 12:44:07 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.251: +23 -6 lines
Log Message:
- implement tag keyword but do not use it yet
- skip_block now skips known types of sub-blocks
- print the decoded filename if possible

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     object *o;
1945     for (o = obj->inv; o; o = o->below)
1946 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1947 root 1.1 }
1948    
1949 root 1.102 void
1950     set_animation (object *op, int idx)
1951     CODE:
1952     SET_ANIMATION (op, idx);
1953    
1954 elmex 1.160 int
1955     num_animations (object *op)
1956     CODE:
1957     RETVAL = NUM_ANIMATIONS (op);
1958     OUTPUT: RETVAL
1959    
1960 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1961     ALIAS:
1962     slot_used = 1
1963     CODE:
1964     {
1965     if (slot >= NUM_BODY_LOCATIONS)
1966     croak ("body slot index out of range");
1967    
1968 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1969 root 1.205
1970     if (items > 2)
1971     if (ix)
1972 root 1.208 op->slot[slot].used = value;
1973     else
1974 root 1.205 op->slot[slot].info = value;
1975     }
1976     OUTPUT:
1977     RETVAL
1978    
1979 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1980 root 1.58
1981     object *find_marked_object (object *op)
1982    
1983 root 1.109 int need_identify (object *obj);
1984 root 1.1
1985     int apply_shop_mat (object *shop_mat, object *op);
1986    
1987 pippijn 1.172 int move_player (object *op, int dir)
1988     CODE:
1989     RETVAL = move_player (op, dir);
1990     OUTPUT:
1991     RETVAL
1992    
1993 root 1.27 int move (object *op, int dir, object *originator = op)
1994     CODE:
1995     RETVAL = move_ob (op, dir, originator);
1996     OUTPUT:
1997     RETVAL
1998 root 1.1
1999 root 1.74 void apply (object *applier, object *applied, int flags = 0)
2000     CODE:
2001     manual_apply (applied, applier, flags);
2002 root 1.1
2003 root 1.74 void apply_below (object *op)
2004     CODE:
2005     player_apply_below (op);
2006 root 1.1
2007 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
2008    
2009 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
2010 root 1.1
2011     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
2012    
2013 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
2014 root 1.1
2015 root 1.116 #//TODO
2016     object *clone_ (object *op, int recursive = 0)
2017 root 1.74 CODE:
2018     if (recursive)
2019     RETVAL = object_create_clone (op);
2020     else
2021     {
2022     RETVAL = object::create ();
2023 root 1.75 op->copy_to (RETVAL);
2024 root 1.74 }
2025     OUTPUT: RETVAL
2026 root 1.1
2027 root 1.74 int pay_item (object *op, object *buyer)
2028     CODE:
2029     RETVAL = pay_for_item (op, buyer);
2030     OUTPUT: RETVAL
2031 root 1.1
2032 root 1.74 int pay_amount (object *op, uint64 amount)
2033     CODE:
2034     RETVAL = pay_for_amount (amount, op);
2035     OUTPUT: RETVAL
2036 root 1.1
2037     void pay_player (object *op, uint64 amount)
2038    
2039 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
2040 root 1.1
2041 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
2042 root 1.1
2043 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
2044     CODE:
2045     do_learn_spell (op, sp, special_prayer);
2046 root 1.1
2047 root 1.74 void forget_spell (object *op, object *sp)
2048     CODE:
2049     do_forget_spell (op, query_name (sp));
2050 root 1.1
2051 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2052 root 1.74 CODE:
2053     RETVAL = check_spell_known (op, spellname);
2054     OUTPUT: RETVAL
2055 root 1.1
2056 root 1.74 int query_money (object *op)
2057 root 1.1 ALIAS: money = 0
2058    
2059 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2060 root 1.1 ALIAS: cost = 0
2061    
2062 root 1.74 void spring_trap (object *op, object *victim)
2063 root 1.1
2064 root 1.74 int check_trigger (object *op, object *cause)
2065 root 1.1
2066 root 1.74 void drop (object *who, object *op)
2067 root 1.1
2068 root 1.74 void pick_up (object *who, object *op)
2069 root 1.1
2070 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
2071 root 1.1
2072 root 1.102 void update_object (object *op, int action)
2073 root 1.1
2074 root 1.183 object *cf_create_object_by_name (utf8_string name)
2075 root 1.1
2076 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2077 root 1.1
2078     void player_lvl_adj (object *who, object *skill = 0)
2079    
2080     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2081    
2082     int calc_skill_exp (object *who, object *op, object *skill);
2083    
2084     void push_button (object *op);
2085    
2086     void use_trigger (object *op);
2087    
2088 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2089 root 1.1
2090     void remove_button_link (object *op);
2091    
2092 elmex 1.232 void handle_apply_yield (object *op);
2093    
2094 root 1.1
2095     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2096    
2097     object *cf_insert_ob_in_ob (object *ob, object *where)
2098    
2099     # no clean way to get an object from an archetype - stupid idiotic
2100     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2101    
2102 root 1.183 object *new (utf8_string archetype = 0)
2103 root 1.1 PROTOTYPE: ;$
2104     CODE:
2105 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2106 root 1.1 OUTPUT:
2107     RETVAL
2108    
2109 root 1.225 object *find_object (U32 tag)
2110    
2111 root 1.218 # TODO: nuke
2112 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2113 root 1.1 PROTOTYPE: $$$$$$
2114     CODE:
2115     {
2116     int unused_type;
2117     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
2118     }
2119    
2120 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
2121 root 1.1
2122 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
2123 root 1.1
2124     object *get_nearest_player (object *ob)
2125     ALIAS: nearest_player = 0
2126     PREINIT:
2127     extern object *get_nearest_player (object *);
2128    
2129     void rangevector (object *ob, object *other, int flags = 0)
2130     PROTOTYPE: $$;$
2131     PPCODE:
2132     {
2133     rv_vector rv;
2134     get_rangevector (ob, other, &rv, flags);
2135     EXTEND (SP, 5);
2136     PUSHs (newSVuv (rv.distance));
2137     PUSHs (newSViv (rv.distance_x));
2138     PUSHs (newSViv (rv.distance_y));
2139     PUSHs (newSViv (rv.direction));
2140     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
2141     }
2142    
2143     bool on_same_map_as (object *ob, object *other)
2144     CODE:
2145     RETVAL = on_same_map (ob, other);
2146     OUTPUT: RETVAL
2147    
2148 root 1.183 const_utf8_string
2149 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2150 root 1.1 CODE:
2151 root 1.58 RETVAL = query_base_name (op, plural);
2152 root 1.1 OUTPUT: RETVAL
2153    
2154 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
2155    
2156 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2157    
2158     player *player (object *op)
2159     CODE:
2160     RETVAL = op->contr;
2161     OUTPUT: RETVAL
2162    
2163 root 1.105 void check_score (object *op)
2164    
2165 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2166 root 1.120 CODE:
2167     new_draw_info (flags, 0, op, txt);
2168 root 1.1
2169     void kill_player (object *op)
2170    
2171 root 1.58 void esrv_update_item (object *op, int what, object *item)
2172     C_ARGS: what, op, item
2173    
2174 root 1.183 int command_summon (object *op, utf8_string params)
2175 root 1.67
2176 root 1.183 int command_arrest (object *op, utf8_string params)
2177 root 1.67
2178 root 1.66
2179 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2180 root 1.1
2181 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2182 root 1.62
2183 root 1.18 int invoke (player *pl, int event, ...)
2184     CODE:
2185     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2186 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2187     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2188 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2189 root 1.18 OUTPUT: RETVAL
2190    
2191 root 1.12 SV *registry (player *pl)
2192 root 1.1
2193 root 1.102 void
2194     save_stats (player *pl)
2195     CODE:
2196     pl->ob->stats.hp = pl->ob->stats.maxhp;
2197     pl->ob->stats.sp = pl->ob->stats.maxsp;
2198     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2199     pl->orig_stats = pl->ob->stats;
2200    
2201 root 1.217 void clear_los (player *pl)
2202    
2203 root 1.1 void cf_player_move (player *pl, int dir)
2204    
2205     bool
2206     cell_visible (player *pl, int dx, int dy)
2207     CODE:
2208 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2209     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2210 root 1.1 OUTPUT:
2211     RETVAL
2212    
2213 root 1.4 void
2214 root 1.1 send (player *pl, SV *packet)
2215     CODE:
2216     {
2217     STRLEN len;
2218     char *buf = SvPVbyte (packet, len);
2219    
2220 root 1.100 if (pl->ns)
2221     pl->ns->send_packet (buf, len);
2222 root 1.1 }
2223    
2224     int
2225     listening (player *pl, int new_value = -1)
2226     CODE:
2227     RETVAL = pl->listening;
2228     if (new_value >= 0)
2229     pl->listening = new_value;
2230     OUTPUT:
2231     RETVAL
2232    
2233 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2234 root 1.45 PROTOTYPE: $;$$$
2235 root 1.1 PPCODE:
2236 root 1.45 if (GIMME_V != G_VOID)
2237     {
2238     EXTEND (SP, 3);
2239     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2240     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2241     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2242     }
2243 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2244     if (x) sv_to (x, pl->bed_x);
2245     if (y) sv_to (y, pl->bed_y);
2246 root 1.1
2247     void
2248     list ()
2249     PPCODE:
2250 root 1.128 for_all_players (pl)
2251 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2252 root 1.1
2253    
2254     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2255    
2256 root 1.61 int invoke (maptile *map, int event, ...)
2257 root 1.18 CODE:
2258     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2259 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2260     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2261 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2262 root 1.25 OUTPUT: RETVAL
2263 root 1.18
2264 root 1.61 SV *registry (maptile *map)
2265 root 1.12
2266 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2267 root 1.1
2268 root 1.116 void
2269     maptile::instantiate ()
2270    
2271     maptile *new ()
2272 root 1.1 PROTOTYPE:
2273     CODE:
2274 root 1.116 RETVAL = new maptile;
2275 root 1.1 OUTPUT:
2276     RETVAL
2277    
2278 root 1.116 void
2279 root 1.117 maptile::players ()
2280     PPCODE:
2281     if (GIMME_V == G_SCALAR)
2282 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2283 root 1.117 else if (GIMME_V == G_ARRAY)
2284     {
2285     EXTEND (SP, THIS->players);
2286     for_all_players (pl)
2287     if (pl->ob && pl->ob->map == THIS)
2288 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2289 root 1.117 }
2290    
2291 root 1.156 void
2292 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2293 root 1.156 CODE:
2294     {
2295 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2296     croak ("maptile::add_underlay: palette must be arrayref");
2297 root 1.156
2298 root 1.168 palette = SvRV (palette);
2299 root 1.156
2300 root 1.168 STRLEN idxlen;
2301     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2302 root 1.156
2303 root 1.168 for (int x = 0; x < THIS->width; ++x)
2304     for (int y = 0; y < THIS->height; ++y)
2305     {
2306     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2307     if (op->flag [FLAG_IS_FLOOR])
2308     goto skip_space;
2309    
2310     {
2311     int offs = offset + y * stride + x;
2312     if (IN_RANGE_EXC (offs, 0, idxlen))
2313     {
2314     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2315     {
2316     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2317     ob->flag [FLAG_NO_MAP_SAVE] = true;
2318     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2319 root 1.200
2320     if (ob->randomitems)
2321     {
2322 root 1.203 if (!ob->above)
2323     {
2324     ob->create_treasure (ob->randomitems);
2325    
2326     for (object *op = ob->above; op; op = op->above)
2327     op->flag [FLAG_NO_MAP_SAVE] = true;
2328     }
2329    
2330 root 1.200 ob->randomitems = 0;
2331     }
2332 root 1.168 }
2333     }
2334     }
2335 root 1.156
2336 root 1.168 skip_space: ;
2337     }
2338     }
2339    
2340     void
2341     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2342     CODE:
2343     {
2344     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2345     croak ("maptile::set_regiondata: palette must be arrayref");
2346    
2347     palette = SvRV (palette);
2348    
2349     STRLEN idxlen;
2350     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2351    
2352 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2353 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2354    
2355     for (int i = av_len ((AV *)palette) + 1; i--; )
2356 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2357 root 1.168
2358     for (int y = 0; y < THIS->height; ++y)
2359     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2360    
2361     sfree (THIS->regions, THIS->size ());
2362 root 1.230 delete [] THIS->regionmap;
2363 root 1.168
2364     THIS->regions = regions;
2365 root 1.156 THIS->regionmap = regionmap;
2366     }
2367    
2368 root 1.193 void
2369     maptile::create_region_treasure ()
2370     CODE:
2371     {
2372     object *op = object::create ();
2373     op->type = FLOOR;
2374     op->map = THIS;
2375    
2376     for (int x = 0; x < THIS->width; ++x)
2377     for (int y = 0; y < THIS->height; ++y)
2378     {
2379     region *rgn = THIS->region (x, y);
2380    
2381     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2382     if (rgn->treasure && rndm () < rgn->treasure_density)
2383     {
2384     op->x = x;
2385     op->y = y;
2386     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2387     }
2388     }
2389    
2390     op->destroy ();
2391     }
2392    
2393 root 1.74 int out_of_map (maptile *map, int x, int y)
2394    
2395 root 1.29 void
2396 root 1.61 trigger (maptile *map, long connection, bool state = true)
2397 root 1.29 CODE:
2398     activate_connection (map, connection, state);
2399    
2400     void
2401 root 1.61 get_connection (maptile *map, long connection)
2402 root 1.29 PPCODE:
2403     oblinkpt *obp = get_connection_links (map, connection);
2404     if (obp)
2405     for (objectlink *ol = obp->link; ol; ol = ol->next)
2406 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2407 root 1.29
2408 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2409 root 1.1
2410 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2411 root 1.1
2412 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2413 root 1.1 C_ARGS: str, map, nx, ny
2414    
2415     void
2416 root 1.140 get_map_flags (maptile *map, int x, int y)
2417 root 1.1 PPCODE:
2418     {
2419 root 1.61 maptile *nmap = 0;
2420 root 1.1 I16 nx = 0, ny = 0;
2421 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2422 root 1.1
2423     EXTEND (SP, 4);
2424     PUSHs (sv_2mortal (newSViv (flags)));
2425    
2426     if (GIMME_V == G_ARRAY)
2427     {
2428     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2429     PUSHs (sv_2mortal (newSViv (nx)));
2430     PUSHs (sv_2mortal (newSViv (ny)));
2431     }
2432     }
2433    
2434     void
2435 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2436 root 1.1 PROTOTYPE: $$$
2437     PPCODE:
2438     {
2439     object *o;
2440 root 1.61 maptile *nmap = 0;
2441 root 1.1 I16 nx, ny;
2442    
2443 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2444 root 1.1
2445     if (nmap)
2446     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2447     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2448     }
2449    
2450     SV *
2451 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2452 root 1.1 PROTOTYPE: $$$
2453     ALIAS:
2454     top_at = 1
2455     flags_at = 2
2456     light_at = 3
2457     move_block_at = 4
2458     move_slow_at = 5
2459     move_on_at = 6
2460     move_off_at = 7
2461     INIT:
2462 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2463 root 1.1 CODE:
2464     switch (ix)
2465     {
2466     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2467     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2468     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2469     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2470     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2471     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2472     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2473     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2474     }
2475 root 1.122 OUTPUT: RETVAL
2476 root 1.1
2477 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2478    
2479     void fix_walls_around (maptile *map, int x, int y)
2480 root 1.1
2481 root 1.117 # worst xs function of my life
2482 root 1.140 bool
2483 root 1.117 _create_random_map (\
2484 root 1.140 maptile *self,\
2485 root 1.183 utf8_string wallstyle,\
2486     utf8_string wall_name,\
2487     utf8_string floorstyle,\
2488     utf8_string monsterstyle,\
2489     utf8_string treasurestyle,\
2490     utf8_string layoutstyle,\
2491     utf8_string doorstyle,\
2492     utf8_string decorstyle,\
2493     utf8_string origin_map,\
2494     utf8_string final_map,\
2495     utf8_string exitstyle,\
2496     utf8_string this_map,\
2497     utf8_string exit_on_final_map,\
2498 root 1.146 int xsize,\
2499     int ysize,\
2500 root 1.117 int expand2x,\
2501     int layoutoptions1,\
2502     int layoutoptions2,\
2503     int layoutoptions3,\
2504     int symmetry,\
2505     int difficulty,\
2506     int difficulty_given,\
2507     float difficulty_increase,\
2508     int dungeon_level,\
2509     int dungeon_depth,\
2510     int decoroptions,\
2511     int orientation,\
2512     int origin_y,\
2513     int origin_x,\
2514 root 1.146 U32 random_seed,\
2515 root 1.117 val64 total_map_hp,\
2516     int map_layout_style,\
2517     int treasureoptions,\
2518     int symmetry_used,\
2519 root 1.137 region *region,\
2520 root 1.183 utf8_string custom\
2521 root 1.117 )
2522     CODE:
2523     {
2524     random_map_params rmp;
2525    
2526     assign (rmp.wallstyle , wallstyle);
2527     assign (rmp.wall_name , wall_name);
2528     assign (rmp.floorstyle , floorstyle);
2529     assign (rmp.monsterstyle , monsterstyle);
2530     assign (rmp.treasurestyle , treasurestyle);
2531     assign (rmp.layoutstyle , layoutstyle);
2532     assign (rmp.doorstyle , doorstyle);
2533     assign (rmp.decorstyle , decorstyle);
2534     assign (rmp.exitstyle , exitstyle);
2535     assign (rmp.exit_on_final_map, exit_on_final_map);
2536    
2537 root 1.122 rmp.origin_map = origin_map;
2538     rmp.final_map = final_map;
2539     rmp.this_map = this_map;
2540 root 1.146 rmp.xsize = xsize;
2541     rmp.ysize = ysize;
2542 root 1.117 rmp.expand2x = expand2x;
2543     rmp.layoutoptions1 = layoutoptions1;
2544     rmp.layoutoptions2 = layoutoptions2;
2545     rmp.layoutoptions3 = layoutoptions3;
2546     rmp.symmetry = symmetry;
2547     rmp.difficulty = difficulty;
2548     rmp.difficulty_given = difficulty_given;
2549     rmp.difficulty_increase = difficulty_increase;
2550     rmp.dungeon_level = dungeon_level;
2551     rmp.dungeon_depth = dungeon_depth;
2552     rmp.decoroptions = decoroptions;
2553     rmp.orientation = orientation;
2554     rmp.origin_y = origin_y;
2555     rmp.origin_x = origin_x;
2556     rmp.random_seed = random_seed;
2557 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2558 root 1.117 rmp.map_layout_style = map_layout_style;
2559     rmp.treasureoptions = treasureoptions;
2560     rmp.symmetry_used = symmetry_used;
2561     rmp.region = region;
2562 root 1.137 rmp.custom = custom;
2563 root 1.117
2564 root 1.140 RETVAL = self->generate_random_map (&rmp);
2565 root 1.117 }
2566     OUTPUT:
2567     RETVAL
2568    
2569 root 1.19 MODULE = cf PACKAGE = cf::arch
2570 root 1.1
2571 root 1.218 int archetypes_size ()
2572     CODE:
2573     RETVAL = archetypes.size ();
2574     OUTPUT: RETVAL
2575    
2576     archetype *archetypes (U32 index)
2577     CODE:
2578     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2579     OUTPUT: RETVAL
2580 root 1.1
2581 root 1.212 object *instantiate (archetype *arch)
2582     CODE:
2583     RETVAL = arch_to_object (arch);
2584     OUTPUT:
2585     RETVAL
2586    
2587 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2588 root 1.1
2589 root 1.19 MODULE = cf PACKAGE = cf::party
2590 root 1.1
2591 root 1.19 partylist *first ()
2592 root 1.1 PROTOTYPE:
2593 root 1.19 CODE:
2594     RETVAL = get_firstparty ();
2595     OUTPUT: RETVAL
2596 root 1.1
2597 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2598 root 1.1
2599 root 1.19 MODULE = cf PACKAGE = cf::region
2600 root 1.1
2601 root 1.161 void
2602     list ()
2603     PPCODE:
2604     for_all_regions (rgn)
2605     XPUSHs (sv_2mortal (to_sv (rgn)));
2606    
2607 root 1.183 region *find (utf8_string name)
2608 root 1.161 PROTOTYPE: $
2609 root 1.19 CODE:
2610 root 1.161 RETVAL = region::find (name);
2611 root 1.19 OUTPUT: RETVAL
2612 root 1.1
2613 root 1.183 region *find_fuzzy (utf8_string name)
2614 root 1.122 PROTOTYPE: $
2615     CODE:
2616 root 1.161 RETVAL = region::find_fuzzy (name);
2617 root 1.122 OUTPUT: RETVAL
2618    
2619 root 1.186 int specificity (region *rgn)
2620     CODE:
2621     RETVAL = 0;
2622     while (rgn = rgn->parent)
2623     RETVAL++;
2624     OUTPUT: RETVAL
2625    
2626 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2627 root 1.1
2628 root 1.19 MODULE = cf PACKAGE = cf::living
2629 root 1.1
2630 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2631 root 1.1
2632 root 1.76 MODULE = cf PACKAGE = cf::settings
2633    
2634 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2635 root 1.76
2636 root 1.84 MODULE = cf PACKAGE = cf::client
2637 root 1.79
2638 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2639 root 1.79
2640 root 1.84 int invoke (client *ns, int event, ...)
2641 root 1.79 CODE:
2642 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2643 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2644     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2645 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2646 root 1.79 OUTPUT: RETVAL
2647    
2648 root 1.84 SV *registry (client *ns)
2649 root 1.79
2650 root 1.100 void
2651     list ()
2652     PPCODE:
2653     EXTEND (SP, clients.size ());
2654     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2655     PUSHs (sv_2mortal (to_sv (*i)));
2656    
2657 root 1.88 void
2658 root 1.100 client::send_packet (SV *packet)
2659     CODE:
2660     {
2661     STRLEN len;
2662     char *buf = SvPVbyte (packet, len);
2663    
2664     THIS->send_packet (buf, len);
2665     }
2666    
2667 root 1.237 faceidx
2668 root 1.238 client::need_face (utf8_string name, int pri = 0)
2669 root 1.237 CODE:
2670 root 1.238 RETVAL = face_find (name, 0);
2671     if (RETVAL)
2672     {
2673     THIS->send_face (RETVAL, pri);
2674     THIS->flush_fx ();
2675     }
2676     OUTPUT:
2677     RETVAL
2678    
2679     int
2680     client::fx_want (int idx, int value = -1)
2681     CODE:
2682     if (0 < idx && idx < FT_NUM)
2683     {
2684     RETVAL = THIS->fx_want [idx];
2685     if (items > 2)
2686     THIS->fx_want [idx] = value;
2687     }
2688     else
2689     RETVAL = 0;
2690 root 1.237 OUTPUT:
2691     RETVAL
2692    
2693 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2694    
2695     faceidx sound_find (utf8_string name)
2696    
2697 root 1.240 void sound_set (utf8_string str, faceidx face)
2698    
2699     # dire hack
2700     void old_sound_index (int idx, faceidx face)
2701     CODE:
2702     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2703     old_sound_index [idx] = face;
2704    
2705 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2706    
2707 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2708 root 1.176
2709 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2710 root 1.176
2711 root 1.183 faceidx alloc (utf8_string name)
2712 root 1.176 CODE:
2713     {
2714     do
2715     {
2716     RETVAL = faces.size ();
2717 root 1.177 faces.resize (RETVAL + 1);
2718 root 1.176 }
2719     while (!RETVAL); // crude way to leave index 0
2720    
2721     faces [RETVAL].name = name;
2722     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2723    
2724     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2725     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2726     }
2727     OUTPUT: RETVAL
2728    
2729 root 1.227 void set_type (faceidx idx, int value)
2730     ALIAS:
2731     set_type = 0
2732     set_visibility = 1
2733     set_magicmap = 2
2734     set_smooth = 3
2735     set_smoothlevel = 4
2736 root 1.176 CODE:
2737 root 1.229 faceinfo *f = face_info (idx); assert (f);
2738 root 1.227 switch (ix)
2739     {
2740     case 0: f->type = value; break;
2741     case 1: f->visibility = value; break;
2742     case 2: f->magicmap = value; break;
2743     case 3: f->smooth = value; break;
2744     case 4: f->smoothlevel = value; break;
2745     }
2746 root 1.177
2747     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2748 root 1.176 CODE:
2749 root 1.182 {
2750 root 1.231 faceinfo *f = face_info (idx); assert (f);
2751     facedata *d = &(faceset ? f->data64 : f->data32);
2752 root 1.181 sv_to (data, d->data);
2753     STRLEN clen;
2754     char *cdata = SvPVbyte (chksum, clen);
2755 root 1.182 clen = min (CHKSUM_SIZE, clen);
2756    
2757     if (memcmp (d->chksum, cdata, clen))
2758     {
2759     memcpy (d->chksum, cdata, clen);
2760    
2761     // invalidate existing client face info
2762     for_all_clients (ns)
2763     if (ns->faceset == faceset)
2764     {
2765     ns->faces_sent [idx] = false;
2766     ns->force_newmap = true;
2767     }
2768     }
2769     }
2770 root 1.176
2771 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2772     CODE:
2773     facedata *d = face_data (idx, faceset); assert (d);
2774     RETVAL = d->data.size ();
2775     OUTPUT:
2776     RETVAL
2777    
2778     SV *get_chksum (faceidx idx, int faceset = 0)
2779     CODE:
2780     facedata *d = face_data (idx, faceset); assert (d);
2781     RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2782     OUTPUT:
2783     RETVAL
2784    
2785 root 1.177 void invalidate (faceidx idx)
2786     CODE:
2787     for_all_clients (ns)
2788 root 1.182 {
2789     ns->faces_sent [idx] = false;
2790     ns->force_newmap = true;
2791     }
2792 root 1.177
2793     void invalidate_all ()
2794     CODE:
2795     for_all_clients (ns)
2796 root 1.182 {
2797     ns->faces_sent.reset ();
2798     ns->force_newmap = true;
2799     }
2800 root 1.177
2801 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2802    
2803     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2804    
2805     animidx anim_find (utf8_string name)
2806     CODE:
2807     RETVAL = animation::find (name).number;
2808     OUTPUT: RETVAL
2809    
2810     animidx set (utf8_string name, SV *frames, int facings = 1)
2811     CODE:
2812     {
2813     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2814     croak ("frames must be an arrayref");
2815    
2816     AV *av = (AV *)SvRV (frames);
2817    
2818     animation *anim = &animation::find (name);
2819     if (anim->number)
2820     {
2821     anim->resize (av_len (av) + 1);
2822     anim->facings = facings;
2823     }
2824     else
2825     anim = &animation::create (name, av_len (av) + 1, facings);
2826    
2827     for (int i = 0; i < anim->num_animations; ++i)
2828     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2829     }
2830     OUTPUT: RETVAL
2831    
2832     void invalidate_all ()
2833     CODE:
2834     for_all_clients (ns)
2835     ns->anims_sent.reset ();
2836    
2837 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2838    
2839     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2840    
2841     SV *
2842     new (char *klass)
2843     CODE:
2844     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2845     OUTPUT: RETVAL
2846    
2847     void
2848     DESTROY (SV *sv)
2849     CODE:
2850     object_freezer *self;
2851     sv_to (sv, self);
2852     delete self;
2853    
2854     MODULE = cf PACKAGE = cf::object::thawer
2855    
2856     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2857    
2858     SV *
2859     new_from_file (char *klass, octet_string path)
2860     CODE:
2861     object_thawer *f = new object_thawer (path);
2862     if (!*f)
2863     {
2864     delete f;
2865     XSRETURN_UNDEF;
2866     }
2867     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2868     OUTPUT: RETVAL
2869    
2870     void
2871     DESTROY (SV *sv)
2872     CODE:
2873     object_thawer *self;
2874     sv_to (sv, self);
2875     delete self;
2876    
2877 root 1.252 void
2878     tags (object_thawer *self)
2879     CODE:
2880     while (self->kw != KW_EOF)
2881     {
2882     if (self->kw == KW_tag)
2883     XPUSHs (sv_2mortal (to_sv (self->get_str ())));
2884    
2885     self->skip ();
2886     }
2887