ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.224
Committed: Tue Jun 26 05:07:21 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.223: +9 -1 lines
Log Message:
again, messages are utf-8 *sigh*

File Contents

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