ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.257
Committed: Sun Sep 30 16:24:31 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.256: +25 -136 lines
Log Message:
finally remove the old buggy plug-in cruft

File Contents

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