ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.229
Committed: Thu Jul 12 08:40:14 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.228: +16 -4 lines
Log Message:
first workable server-side music implementation

File Contents

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