ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.227
Committed: Tue Jul 10 16:24:00 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.226: +15 -9 lines
Log Message:
*** empty log message ***

File Contents

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