ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.254
Committed: Mon Sep 10 18:30:30 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
CVS Tags: rel-2_2
Changes since 1.253: +5 -4 lines
Log Message:
- note to self: all forms of cede need PUTBACK
  as any other fucntion modifying the stack.
- the beginning of tag support
- just for fun tag soem buildings in scorn and watch the database change
- do not install world-precomposed, this saves a lot of traffic, scanning
  and other things.
- add tag field to every object in the editor.

File Contents

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