ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.225
Committed: Sat Jun 30 03:00:55 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.224: +2 -5 lines
Log Message:
*** empty log message ***

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