ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.245
Committed: Thu Aug 30 05:24:14 2007 UTC (16 years, 8 months ago) by root
Branch: MAIN
Changes since 1.244: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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