ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.243
Committed: Fri Aug 24 00:26:10 2007 UTC (16 years, 9 months ago) by root
Branch: MAIN
Changes since 1.242: +3 -2 lines
Log Message:
major changes:

- on_same_map and related functions now do not block on map loads, instead
  they pretend the map is not there. this ensures lag-free operation, but changes
  semantics considerably: running quickly over the worldmap often lets you bump
  into map borders until the map has been loaded. also, rabies takes longer
  to nuke a full continent now.
- mapinfo (a major sync blocker) is now fully asynchronous, and works by
  quieing all mapinfo requests and retrying them on every tick until satisfed.

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.116 maptile *
1049 root 1.126 maptile::find_sync (const char *path, maptile *origin)
1050 root 1.116 {
1051     CALL_BEGIN (2);
1052     CALL_ARG (path);
1053     CALL_ARG (origin);
1054 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
1055 root 1.116
1056     maptile *retval;
1057    
1058     if (count)
1059     sv_to (POPs, retval);
1060     else
1061     retval = 0;
1062    
1063     CALL_END;
1064    
1065     return retval;
1066     }
1067    
1068 root 1.135 maptile *
1069 root 1.243 maptile::find_async (const char *path, maptile *origin, bool load)
1070 root 1.135 {
1071 root 1.243 CALL_BEGIN (3);
1072 root 1.135 CALL_ARG (path);
1073     CALL_ARG (origin);
1074 root 1.243 CALL_ARG (load);
1075 root 1.135 CALL_CALL ("cf::map::find_async", G_SCALAR);
1076    
1077     maptile *retval;
1078    
1079     if (count)
1080     sv_to (POPs, retval);
1081     else
1082     retval = 0;
1083    
1084     CALL_END;
1085    
1086     return retval;
1087     }
1088    
1089 root 1.116 void
1090 root 1.126 maptile::do_load_sync ()
1091     {
1092     CALL_BEGIN (1);
1093     CALL_ARG (this);
1094     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
1095     CALL_END;
1096     }
1097    
1098     void
1099 root 1.116 maptile::change_all_map_light (int change)
1100     {
1101     CALL_BEGIN (1);
1102     CALL_ARG (change);
1103     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
1104     CALL_END;
1105     }
1106    
1107     void
1108     object::enter_exit (object *exit)
1109     {
1110     if (type != PLAYER)
1111     return;
1112    
1113     CALL_BEGIN (2);
1114     CALL_ARG (this);
1115     CALL_ARG (exit);
1116     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
1117     CALL_END;
1118     }
1119    
1120 root 1.198 void
1121     log_backtrace (const char *msg)
1122     {
1123     #if HAVE_BACKTRACE
1124     void *addr [20];
1125     int size = backtrace (addr, 20);
1126    
1127     CALL_BEGIN (size);
1128     CALL_ARG (msg);
1129     for (int i = 0; i < size; ++i)
1130     CALL_ARG ((IV)addr [i]);
1131     CALL_CALL ("cf::_log_backtrace", G_VOID);
1132     CALL_END;
1133     #endif
1134     }
1135    
1136 root 1.116 /////////////////////////////////////////////////////////////////////////////
1137    
1138 root 1.80 struct EventAPI *watcher_base::GEventAPI;
1139 root 1.116 struct CoroAPI *coroapi::GCoroAPI;
1140 root 1.80
1141 root 1.124 int coroapi::cede_counter;
1142 root 1.220 tstamp coroapi::next_cede;
1143 root 1.189
1144     void coroapi::do_cede_to_tick ()
1145     {
1146     cede_counter = 0;
1147    
1148     cede ();
1149    
1150     next_cede += (TICK / CEDES_PER_TICK) * 0.99;
1151     if (next_cede > SvNV (sv_next_tick) - 0.02)
1152     next_cede = SvNV (sv_next_tick);
1153     }
1154    
1155     void coroapi::do_cede_every ()
1156     {
1157     cede_counter = 0;
1158    
1159     if (coroapi::nready ())
1160     coroapi::cede ();
1161     }
1162    
1163     void coroapi::do_cede_to_tick_every ()
1164     {
1165     cede_counter = 0;
1166    
1167     cede_to_tick ();
1168     }
1169 root 1.124
1170 root 1.188 void
1171     coroapi::wait_for_tick ()
1172     {
1173     CALL_BEGIN (0);
1174     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1175     CALL_END;
1176     }
1177    
1178     void
1179     coroapi::wait_for_tick_begin ()
1180     {
1181     CALL_BEGIN (0);
1182     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1183     CALL_END;
1184     }
1185    
1186     static void
1187     iw_dispatch (pe_event *ev)
1188 root 1.85 {
1189     iw *w = (iw *)ev->ext_data;
1190     w->call (*w);
1191     }
1192    
1193     void
1194     iw::alloc ()
1195     {
1196     pe = GEventAPI->new_idle (0, 0);
1197    
1198 root 1.150 WaREENTRANT_off (pe);
1199 root 1.85 pe->base.callback = (void *)iw_dispatch;
1200     pe->base.ext_data = (void *)this;
1201     }
1202    
1203 root 1.80 static void iow_dispatch (pe_event *ev)
1204     {
1205     iow *w = (iow *)ev->ext_data;
1206     w->call (*w, ((pe_ioevent *)ev)->got);
1207     }
1208    
1209     void
1210     iow::alloc ()
1211     {
1212     pe = GEventAPI->new_io (0, 0);
1213    
1214 root 1.150 WaREENTRANT_off (pe);
1215 root 1.80 pe->base.callback = (void *)iow_dispatch;
1216     pe->base.ext_data = (void *)this;
1217    
1218 root 1.81 pe->fd = -1;
1219     pe->poll = 0;
1220 root 1.80 }
1221    
1222 root 1.85 void
1223 root 1.80 iow::fd (int fd)
1224     {
1225     pe->fd = fd;
1226     }
1227    
1228     int
1229     iow::poll ()
1230     {
1231     return pe->poll;
1232     }
1233    
1234 root 1.85 void
1235 root 1.80 iow::poll (int events)
1236     {
1237 root 1.81 if (pe->poll != events)
1238     {
1239     if (pe->poll) stop ();
1240     pe->poll = events;
1241     if (pe->poll) start ();
1242     }
1243 root 1.80 }
1244    
1245 root 1.109 void
1246     _connect_to_perl ()
1247     {
1248     stash_cf = gv_stashpv ("cf" , 1);
1249    
1250     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1251     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1252     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1253     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1254     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1255     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1256     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1257     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1258     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1259    
1260 root 1.189 sv_runtime = get_sv ("cf::RUNTIME" , 1); sv_upgrade (sv_runtime , SVt_NV);
1261     sv_next_tick = get_sv ("cf::NEXT_TICK", 1); sv_upgrade (sv_next_tick, SVt_NV);
1262 root 1.116
1263 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1264     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1265     cb_object = get_av ("cf::CB_OBJECT", 1);
1266     cb_player = get_av ("cf::CB_PLAYER", 1);
1267     cb_client = get_av ("cf::CB_CLIENT", 1);
1268     cb_type = get_av ("cf::CB_TYPE" , 1);
1269     cb_map = get_av ("cf::CB_MAP" , 1);
1270     }
1271    
1272 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1273    
1274     BOOT:
1275     {
1276 root 1.116 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1277     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1278 root 1.80
1279 root 1.189 _connect_to_perl ();
1280    
1281 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1282 root 1.63
1283 root 1.220 //{
1284     // require_pv ("Time::HiRes");
1285     //
1286     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1287     // if (!svp) croak ("Time::HiRes is required");
1288     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1289     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1290     //}
1291 root 1.189
1292 root 1.1 static const struct {
1293     const char *name;
1294     IV iv;
1295     } *civ, const_iv[] = {
1296     # define const_iv(name) { # name, (IV)name },
1297 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1298 root 1.198 const_iv (logBacktrace)
1299 root 1.180
1300 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1301    
1302     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1303 root 1.180
1304 root 1.5 const_iv (MAX_TIME)
1305 root 1.189
1306 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1307     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1308     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1309     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1310     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1311     const_iv (body_wrist) const_iv (body_waist)
1312 root 1.205
1313 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1314     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1315     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1316     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1317     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1318     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1319     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1320     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1321     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1322     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1323     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1324     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1325     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1326     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1327     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1328     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1329     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1330     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1331     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1332     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1333     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1334     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1335     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1336     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1337     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1338     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1339     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1340     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1341 root 1.1
1342 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1343 root 1.14
1344 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1345     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1346 root 1.1
1347 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1348     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1349     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1350     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1351     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1352     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1353     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1354    
1355     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1356     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1357 root 1.1 const_iv (WEAP_BLUD)
1358    
1359 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1360 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1361 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1362     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1363     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1364     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1365     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1366     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1367     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1368     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1369     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1370     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1371     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1372     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1373     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1374     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1375     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1376     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1377     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1378     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1379     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1380     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1381     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1382     const_iv (FLAG_OBJ_SAVE_ON_OVL) const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1383     const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1384     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1385    
1386     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1387     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1388     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1389     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1390 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1391     const_iv (NDI_NOCREATE)
1392 root 1.1
1393 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1394     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1395    
1396     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1397    
1398 root 1.212 const_iv (SP_RAISE_DEAD)
1399     const_iv (SP_RUNE)
1400     const_iv (SP_MAKE_MARK)
1401     const_iv (SP_BOLT)
1402     const_iv (SP_BULLET)
1403     const_iv (SP_EXPLOSION)
1404     const_iv (SP_CONE)
1405     const_iv (SP_BOMB)
1406     const_iv (SP_WONDER)
1407     const_iv (SP_SMITE)
1408     const_iv (SP_MAGIC_MISSILE)
1409     const_iv (SP_SUMMON_GOLEM)
1410     const_iv (SP_DIMENSION_DOOR)
1411     const_iv (SP_MAGIC_MAPPING)
1412     const_iv (SP_MAGIC_WALL)
1413     const_iv (SP_DESTRUCTION)
1414     const_iv (SP_PERCEIVE_SELF)
1415     const_iv (SP_WORD_OF_RECALL)
1416     const_iv (SP_INVISIBLE)
1417     const_iv (SP_PROBE)
1418     const_iv (SP_HEALING)
1419     const_iv (SP_CREATE_FOOD)
1420     const_iv (SP_EARTH_TO_DUST)
1421     const_iv (SP_CHANGE_ABILITY)
1422     const_iv (SP_BLESS)
1423     const_iv (SP_CURSE)
1424     const_iv (SP_SUMMON_MONSTER)
1425     const_iv (SP_CHARGING)
1426     const_iv (SP_POLYMORPH)
1427     const_iv (SP_ALCHEMY)
1428     const_iv (SP_REMOVE_CURSE)
1429     const_iv (SP_IDENTIFY)
1430     const_iv (SP_DETECTION)
1431     const_iv (SP_MOOD_CHANGE)
1432     const_iv (SP_MOVING_BALL)
1433     const_iv (SP_SWARM)
1434     const_iv (SP_CHANGE_MANA)
1435     const_iv (SP_DISPEL_RUNE)
1436     const_iv (SP_CREATE_MISSILE)
1437     const_iv (SP_CONSECRATE)
1438     const_iv (SP_ANIMATE_WEAPON)
1439     const_iv (SP_LIGHT)
1440     const_iv (SP_CHANGE_MAP_LIGHT)
1441     const_iv (SP_FAERY_FIRE)
1442     const_iv (SP_CAUSE_DISEASE)
1443     const_iv (SP_AURA)
1444     const_iv (SP_TOWN_PORTAL)
1445     const_iv (SP_PARTY_SPELL)
1446    
1447 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1448     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1449 root 1.1 const_iv (F_LOCKED)
1450    
1451 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1452    
1453     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1454     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1455    
1456     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1457    
1458     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1459     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1460    
1461     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1462     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1463    
1464     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1465    
1466     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1467     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1468     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1469     const_iv (M_ICE) const_iv (M_SPECIAL)
1470    
1471     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1472     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1473    
1474     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1475     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1476     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1477     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1478     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1479     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1480     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1481     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1482     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1483     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1484 root 1.1 const_iv (SK_POISON_NAIL)
1485    
1486 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1487     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1488     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1489     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1490     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1491     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1492    
1493     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1494    
1495     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1496     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1497     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1498     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1499     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1500     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1501     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1502    
1503     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1504    
1505     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1506     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1507    
1508     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1509    
1510     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1511 root 1.99
1512 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1513 root 1.117
1514     // random map generator
1515 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1516     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1517    
1518     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1519     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1520     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1521    
1522     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1523     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1524 root 1.195
1525     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1526     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1527     const_iv (GT_MINIMAL)
1528 root 1.238
1529     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1530     const_iv (FT_RSRC) const_iv (FT_NUM)
1531 root 1.1 };
1532    
1533     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1534 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1535 root 1.1
1536     static const struct {
1537     const char *name;
1538 root 1.14 int skip;
1539 root 1.7 IV klass;
1540 root 1.1 IV iv;
1541 root 1.6 } *eiv, event_iv[] = {
1542 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1543 root 1.6 # include "eventinc.h"
1544     # undef def
1545     };
1546    
1547     AV *av = get_av ("cf::EVENT", 1);
1548    
1549     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1550 root 1.7 {
1551     AV *event = newAV ();
1552 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1553 root 1.7 av_push (event, newSViv (eiv->klass));
1554     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1555 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1556 root 1.7 }
1557 root 1.14 }
1558    
1559 root 1.109 void _connect_to_perl ()
1560 root 1.14
1561 root 1.210 void _recalc_want ()
1562    
1563 root 1.47 void _global_reattach ()
1564 root 1.14 CODE:
1565     {
1566     // reattach to all attachable objects in the game.
1567 root 1.128 for_all_clients (ns)
1568     ns->reattach ();
1569 root 1.96
1570 root 1.128 for_all_objects (op)
1571 root 1.109 op->reattach ();
1572 root 1.1 }
1573    
1574 root 1.192 # support function for map-world.ext
1575     void _quantise (SV *data_sv, SV *plt_sv)
1576     CODE:
1577     {
1578     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1579     croak ("_quantise called with invalid agruments");
1580    
1581     plt_sv = SvRV (plt_sv);
1582     SV **plt = AvARRAY (plt_sv);
1583     int plt_count = AvFILL (plt_sv) + 1;
1584    
1585     STRLEN len;
1586     char *data = SvPVbyte (data_sv, len);
1587     char *dst = data;
1588    
1589     while (len >= 3)
1590     {
1591     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1592     {
1593     char *val = SvPVX (*val_sv);
1594    
1595     if (val [0] == data [0]
1596     && val [1] == data [1]
1597     && val [2] == data [2])
1598     {
1599     *dst++ = val [3];
1600     goto next;
1601     }
1602     }
1603    
1604     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1605     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1606     dst - SvPVX (data_sv), len);
1607    
1608     next:
1609     data += 3;
1610     len -= 3;
1611     }
1612    
1613     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1614     }
1615    
1616 root 1.236 void _post_tick ()
1617     CODE:
1618     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1619    
1620     NV till_cede ()
1621     CODE:
1622     RETVAL = coroapi::next_cede - now ();
1623     OUTPUT:
1624     RETVAL
1625    
1626     NV till_tick ()
1627     CODE:
1628     RETVAL = SvNV (sv_next_tick) - now ();
1629     OUTPUT:
1630     RETVAL
1631    
1632 root 1.1 NV floor (NV x)
1633    
1634     NV ceil (NV x)
1635    
1636 root 1.143 NV rndm (...)
1637     CODE:
1638     switch (items)
1639     {
1640     case 0: RETVAL = rndm (); break;
1641     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1642     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1643     default: croak ("cf::rndm requires none, one or two parameters."); break;
1644     }
1645     OUTPUT:
1646     RETVAL
1647    
1648 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1649     CODE:
1650     RETVAL = clamp (value, min_value, max_value);
1651     OUTPUT:
1652     RETVAL
1653    
1654     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1655     CODE:
1656     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1657     OUTPUT:
1658     RETVAL
1659    
1660     void cede_to_tick ()
1661     CODE:
1662     coroapi::cede_to_tick ();
1663    
1664 root 1.5 void server_tick ()
1665 root 1.116 CODE:
1666 root 1.220 NOW = now ();
1667 root 1.116 runtime = SvNVx (sv_runtime);
1668     server_tick ();
1669 root 1.5
1670 root 1.1 void
1671 root 1.198 log_backtrace (utf8_string msg)
1672    
1673     void
1674     LOG (int flags, utf8_string msg)
1675 root 1.1 PROTOTYPE: $$
1676 root 1.198 C_ARGS: flags, "%s", msg
1677 root 1.1
1678 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1679 root 1.1 PROTOTYPE: $$
1680    
1681 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1682 root 1.1 PROTOTYPE: $$
1683    
1684     void
1685     sub_generation_inc ()
1686     CODE:
1687     PL_sub_generation++;
1688    
1689 root 1.183 const_octet_string
1690 root 1.1 mapdir ()
1691     PROTOTYPE:
1692     ALIAS:
1693     mapdir = 0
1694     uniquedir = 1
1695     tmpdir = 2
1696     confdir = 3
1697     localdir = 4
1698     playerdir = 5
1699     datadir = 6
1700     CODE:
1701 root 1.19 switch (ix)
1702     {
1703     case 0: RETVAL = settings.mapdir ; break;
1704     case 1: RETVAL = settings.uniquedir; break;
1705     case 2: RETVAL = settings.tmpdir ; break;
1706     case 3: RETVAL = settings.confdir ; break;
1707     case 4: RETVAL = settings.localdir ; break;
1708     case 5: RETVAL = settings.playerdir; break;
1709     case 6: RETVAL = settings.datadir ; break;
1710     }
1711 root 1.1 OUTPUT: RETVAL
1712    
1713 root 1.120 void abort ()
1714    
1715 root 1.199 void reset_signals ()
1716    
1717 root 1.183 void fork_abort (octet_string cause = "cf::fork_abort")
1718 root 1.144
1719 root 1.183 void cleanup (octet_string cause, bool make_core = false)
1720 root 1.134
1721 root 1.116 void emergency_save ()
1722    
1723 root 1.156 void _exit (int status = EXIT_SUCCESS)
1724    
1725 root 1.149 UV sv_2watcher (SV *w)
1726     CODE:
1727     RETVAL = (UV)GEventAPI->sv_2watcher (w);
1728     OUTPUT:
1729     RETVAL
1730    
1731 root 1.125 #if _POSIX_MEMLOCK
1732    
1733     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1734    
1735     int munlockall ()
1736    
1737     #endif
1738    
1739 root 1.183 int find_animation (utf8_string text)
1740 root 1.1 PROTOTYPE: $
1741    
1742 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1743 root 1.1
1744 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1745 root 1.1
1746     int
1747     exp_to_level (val64 exp)
1748     CODE:
1749     {
1750     int i = 0;
1751    
1752     RETVAL = settings.max_level;
1753    
1754     for (i = 1; i <= settings.max_level; i++)
1755     {
1756     if (levels[i] > exp)
1757     {
1758     RETVAL = i - 1;
1759     break;
1760     }
1761     }
1762     }
1763     OUTPUT: RETVAL
1764    
1765     val64
1766     level_to_min_exp (int level)
1767     CODE:
1768     if (level > settings.max_level)
1769     RETVAL = levels[settings.max_level];
1770     else if (level < 1)
1771     RETVAL = 0;
1772     else
1773     RETVAL = levels[level];
1774     OUTPUT: RETVAL
1775    
1776     SV *
1777     resistance_to_string (int atnr)
1778     CODE:
1779     if (atnr >= 0 && atnr < NROFATTACKS)
1780     RETVAL = newSVpv (resist_plus[atnr], 0);
1781     else
1782     XSRETURN_UNDEF;
1783     OUTPUT: RETVAL
1784    
1785 root 1.162 bool
1786 root 1.183 load_resource_file (octet_string filename)
1787 root 1.162
1788 root 1.97 MODULE = cf PACKAGE = cf::attachable
1789    
1790 root 1.27 int
1791 root 1.97 valid (SV *obj)
1792 root 1.27 CODE:
1793     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1794     OUTPUT:
1795     RETVAL
1796    
1797 root 1.164 void
1798     debug_trace (attachable *obj, bool on = true)
1799     CODE:
1800     obj->flags &= ~attachable::F_DEBUG_TRACE;
1801     if (on)
1802     obj->flags |= attachable::F_DEBUG_TRACE;
1803    
1804 root 1.153 int mortals_size ()
1805     CODE:
1806     RETVAL = attachable::mortals.size ();
1807     OUTPUT: RETVAL
1808    
1809     #object *mortals (U32 index)
1810     # CODE:
1811     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1812     # OUTPUT: RETVAL
1813    
1814 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1815 root 1.115
1816 root 1.101 MODULE = cf PACKAGE = cf::global
1817    
1818     int invoke (SV *klass, int event, ...)
1819     CODE:
1820     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1821     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1822     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1823 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1824 root 1.101 OUTPUT: RETVAL
1825    
1826 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1827    
1828 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1829 root 1.62
1830 root 1.18 int invoke (object *op, int event, ...)
1831     CODE:
1832     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1833 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1834     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1835 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1836 root 1.18 OUTPUT: RETVAL
1837    
1838     SV *registry (object *op)
1839    
1840 root 1.134 int objects_size ()
1841     CODE:
1842     RETVAL = objects.size ();
1843     OUTPUT: RETVAL
1844    
1845     object *objects (U32 index)
1846     CODE:
1847     RETVAL = index < objects.size () ? objects [index] : 0;
1848     OUTPUT: RETVAL
1849    
1850     int actives_size ()
1851     CODE:
1852     RETVAL = actives.size ();
1853     OUTPUT: RETVAL
1854    
1855     object *actives (U32 index)
1856 root 1.57 CODE:
1857 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1858 root 1.57 OUTPUT: RETVAL
1859    
1860 root 1.215 const char *slot_use_name (U32 slot)
1861 root 1.205 ALIAS:
1862 root 1.215 slot_nonuse_name = 1
1863 root 1.205 CODE:
1864     {
1865     if (slot >= NUM_BODY_LOCATIONS)
1866     croak ("body slot index out of range");
1867    
1868     switch (ix)
1869     {
1870 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1871     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1872 root 1.205 }
1873     }
1874     OUTPUT:
1875     RETVAL
1876    
1877 root 1.1 # missing properties
1878    
1879 root 1.54 object *head (object *op)
1880     PROTOTYPE: $
1881     CODE:
1882 root 1.134 RETVAL = op->head_ ();
1883 root 1.54 OUTPUT: RETVAL
1884    
1885 root 1.1 void
1886     inv (object *obj)
1887     PROTOTYPE: $
1888     PPCODE:
1889     {
1890     object *o;
1891     for (o = obj->inv; o; o = o->below)
1892 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1893 root 1.1 }
1894    
1895 root 1.102 void
1896     set_animation (object *op, int idx)
1897     CODE:
1898     SET_ANIMATION (op, idx);
1899    
1900 elmex 1.160 int
1901     num_animations (object *op)
1902     CODE:
1903     RETVAL = NUM_ANIMATIONS (op);
1904     OUTPUT: RETVAL
1905    
1906 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1907     ALIAS:
1908     slot_used = 1
1909     CODE:
1910     {
1911     if (slot >= NUM_BODY_LOCATIONS)
1912     croak ("body slot index out of range");
1913    
1914 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1915 root 1.205
1916     if (items > 2)
1917     if (ix)
1918 root 1.208 op->slot[slot].used = value;
1919     else
1920 root 1.205 op->slot[slot].info = value;
1921     }
1922     OUTPUT:
1923     RETVAL
1924    
1925 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1926 root 1.58
1927     object *find_marked_object (object *op)
1928    
1929 root 1.109 int need_identify (object *obj);
1930 root 1.1
1931     int apply_shop_mat (object *shop_mat, object *op);
1932    
1933 pippijn 1.172 int move_player (object *op, int dir)
1934     CODE:
1935     RETVAL = move_player (op, dir);
1936     OUTPUT:
1937     RETVAL
1938    
1939 root 1.27 int move (object *op, int dir, object *originator = op)
1940     CODE:
1941     RETVAL = move_ob (op, dir, originator);
1942     OUTPUT:
1943     RETVAL
1944 root 1.1
1945 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1946     CODE:
1947     manual_apply (applied, applier, flags);
1948 root 1.1
1949 root 1.74 void apply_below (object *op)
1950     CODE:
1951     player_apply_below (op);
1952 root 1.1
1953 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1954    
1955 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1956 root 1.1
1957     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1958    
1959 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1960 root 1.1
1961 root 1.116 #//TODO
1962     object *clone_ (object *op, int recursive = 0)
1963 root 1.74 CODE:
1964     if (recursive)
1965     RETVAL = object_create_clone (op);
1966     else
1967     {
1968     RETVAL = object::create ();
1969 root 1.75 op->copy_to (RETVAL);
1970 root 1.74 }
1971     OUTPUT: RETVAL
1972 root 1.1
1973 root 1.74 int pay_item (object *op, object *buyer)
1974     CODE:
1975     RETVAL = pay_for_item (op, buyer);
1976     OUTPUT: RETVAL
1977 root 1.1
1978 root 1.74 int pay_amount (object *op, uint64 amount)
1979     CODE:
1980     RETVAL = pay_for_amount (amount, op);
1981     OUTPUT: RETVAL
1982 root 1.1
1983     void pay_player (object *op, uint64 amount)
1984    
1985 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1986 root 1.1
1987 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1988 root 1.1
1989 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1990     CODE:
1991     do_learn_spell (op, sp, special_prayer);
1992 root 1.1
1993 root 1.74 void forget_spell (object *op, object *sp)
1994     CODE:
1995     do_forget_spell (op, query_name (sp));
1996 root 1.1
1997 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1998 root 1.74 CODE:
1999     RETVAL = check_spell_known (op, spellname);
2000     OUTPUT: RETVAL
2001 root 1.1
2002 root 1.74 int query_money (object *op)
2003 root 1.1 ALIAS: money = 0
2004    
2005 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2006 root 1.1 ALIAS: cost = 0
2007    
2008 root 1.74 void spring_trap (object *op, object *victim)
2009 root 1.1
2010 root 1.74 int check_trigger (object *op, object *cause)
2011 root 1.1
2012 root 1.74 void drop (object *who, object *op)
2013 root 1.1
2014 root 1.74 void pick_up (object *who, object *op)
2015 root 1.1
2016 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
2017 root 1.1
2018 root 1.102 void update_object (object *op, int action)
2019 root 1.1
2020 root 1.183 object *cf_create_object_by_name (utf8_string name)
2021 root 1.1
2022 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2023 root 1.1
2024     void player_lvl_adj (object *who, object *skill = 0)
2025    
2026     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2027    
2028     int calc_skill_exp (object *who, object *op, object *skill);
2029    
2030     void push_button (object *op);
2031    
2032     void use_trigger (object *op);
2033    
2034 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2035 root 1.1
2036     void remove_button_link (object *op);
2037    
2038 elmex 1.232 void handle_apply_yield (object *op);
2039    
2040 root 1.1
2041     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2042    
2043     object *cf_insert_ob_in_ob (object *ob, object *where)
2044    
2045     # no clean way to get an object from an archetype - stupid idiotic
2046     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2047    
2048 root 1.183 object *new (utf8_string archetype = 0)
2049 root 1.1 PROTOTYPE: ;$
2050     CODE:
2051 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2052 root 1.1 OUTPUT:
2053     RETVAL
2054    
2055 root 1.225 object *find_object (U32 tag)
2056    
2057 root 1.218 # TODO: nuke
2058 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2059 root 1.1 PROTOTYPE: $$$$$$
2060     CODE:
2061     {
2062     int unused_type;
2063     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
2064     }
2065    
2066 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
2067 root 1.1
2068 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
2069 root 1.1
2070     object *get_nearest_player (object *ob)
2071     ALIAS: nearest_player = 0
2072     PREINIT:
2073     extern object *get_nearest_player (object *);
2074    
2075     void rangevector (object *ob, object *other, int flags = 0)
2076     PROTOTYPE: $$;$
2077     PPCODE:
2078     {
2079     rv_vector rv;
2080     get_rangevector (ob, other, &rv, flags);
2081     EXTEND (SP, 5);
2082     PUSHs (newSVuv (rv.distance));
2083     PUSHs (newSViv (rv.distance_x));
2084     PUSHs (newSViv (rv.distance_y));
2085     PUSHs (newSViv (rv.direction));
2086     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
2087     }
2088    
2089     bool on_same_map_as (object *ob, object *other)
2090     CODE:
2091     RETVAL = on_same_map (ob, other);
2092     OUTPUT: RETVAL
2093    
2094 root 1.183 const_utf8_string
2095 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2096 root 1.1 CODE:
2097 root 1.58 RETVAL = query_base_name (op, plural);
2098 root 1.1 OUTPUT: RETVAL
2099    
2100 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
2101    
2102 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2103    
2104     player *player (object *op)
2105     CODE:
2106     RETVAL = op->contr;
2107     OUTPUT: RETVAL
2108    
2109 root 1.105 void check_score (object *op)
2110    
2111 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2112 root 1.120 CODE:
2113     new_draw_info (flags, 0, op, txt);
2114 root 1.1
2115     void kill_player (object *op)
2116    
2117 root 1.58 void esrv_update_item (object *op, int what, object *item)
2118     C_ARGS: what, op, item
2119    
2120 root 1.183 int command_summon (object *op, utf8_string params)
2121 root 1.67
2122 root 1.183 int command_arrest (object *op, utf8_string params)
2123 root 1.67
2124 root 1.66
2125 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2126 root 1.1
2127 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2128 root 1.62
2129 root 1.18 int invoke (player *pl, int event, ...)
2130     CODE:
2131     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2132 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2133     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2134 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2135 root 1.18 OUTPUT: RETVAL
2136    
2137 root 1.12 SV *registry (player *pl)
2138 root 1.1
2139 root 1.102 void
2140     save_stats (player *pl)
2141     CODE:
2142     pl->ob->stats.hp = pl->ob->stats.maxhp;
2143     pl->ob->stats.sp = pl->ob->stats.maxsp;
2144     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2145     pl->orig_stats = pl->ob->stats;
2146    
2147 root 1.217 void clear_los (player *pl)
2148    
2149 root 1.1 void cf_player_move (player *pl, int dir)
2150    
2151     bool
2152     cell_visible (player *pl, int dx, int dy)
2153     CODE:
2154 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2155     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2156 root 1.1 OUTPUT:
2157     RETVAL
2158    
2159 root 1.4 void
2160 root 1.1 send (player *pl, SV *packet)
2161     CODE:
2162     {
2163     STRLEN len;
2164     char *buf = SvPVbyte (packet, len);
2165    
2166 root 1.100 if (pl->ns)
2167     pl->ns->send_packet (buf, len);
2168 root 1.1 }
2169    
2170     int
2171     listening (player *pl, int new_value = -1)
2172     CODE:
2173     RETVAL = pl->listening;
2174     if (new_value >= 0)
2175     pl->listening = new_value;
2176     OUTPUT:
2177     RETVAL
2178    
2179 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2180 root 1.45 PROTOTYPE: $;$$$
2181 root 1.1 PPCODE:
2182 root 1.45 if (GIMME_V != G_VOID)
2183     {
2184     EXTEND (SP, 3);
2185     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2186     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2187     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2188     }
2189 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2190     if (x) sv_to (x, pl->bed_x);
2191     if (y) sv_to (y, pl->bed_y);
2192 root 1.1
2193     void
2194     list ()
2195     PPCODE:
2196 root 1.128 for_all_players (pl)
2197 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2198 root 1.1
2199    
2200     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2201    
2202 root 1.61 int invoke (maptile *map, int event, ...)
2203 root 1.18 CODE:
2204     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2205 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2206     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2207 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2208 root 1.25 OUTPUT: RETVAL
2209 root 1.18
2210 root 1.61 SV *registry (maptile *map)
2211 root 1.12
2212 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2213 root 1.1
2214 root 1.116 void
2215     maptile::instantiate ()
2216    
2217     maptile *new ()
2218 root 1.1 PROTOTYPE:
2219     CODE:
2220 root 1.116 RETVAL = new maptile;
2221 root 1.1 OUTPUT:
2222     RETVAL
2223    
2224 root 1.116 void
2225 root 1.117 maptile::players ()
2226     PPCODE:
2227     if (GIMME_V == G_SCALAR)
2228 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2229 root 1.117 else if (GIMME_V == G_ARRAY)
2230     {
2231     EXTEND (SP, THIS->players);
2232     for_all_players (pl)
2233     if (pl->ob && pl->ob->map == THIS)
2234 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2235 root 1.117 }
2236    
2237 root 1.156 void
2238 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2239 root 1.156 CODE:
2240     {
2241 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2242     croak ("maptile::add_underlay: palette must be arrayref");
2243 root 1.156
2244 root 1.168 palette = SvRV (palette);
2245 root 1.156
2246 root 1.168 STRLEN idxlen;
2247     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2248 root 1.156
2249 root 1.168 for (int x = 0; x < THIS->width; ++x)
2250     for (int y = 0; y < THIS->height; ++y)
2251     {
2252     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2253     if (op->flag [FLAG_IS_FLOOR])
2254     goto skip_space;
2255    
2256     {
2257     int offs = offset + y * stride + x;
2258     if (IN_RANGE_EXC (offs, 0, idxlen))
2259     {
2260     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2261     {
2262     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2263     ob->flag [FLAG_NO_MAP_SAVE] = true;
2264     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2265 root 1.200
2266     if (ob->randomitems)
2267     {
2268 root 1.203 if (!ob->above)
2269     {
2270     ob->create_treasure (ob->randomitems);
2271    
2272     for (object *op = ob->above; op; op = op->above)
2273     op->flag [FLAG_NO_MAP_SAVE] = true;
2274     }
2275    
2276 root 1.200 ob->randomitems = 0;
2277     }
2278 root 1.168 }
2279     }
2280     }
2281 root 1.156
2282 root 1.168 skip_space: ;
2283     }
2284     }
2285    
2286     void
2287     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2288     CODE:
2289     {
2290     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2291     croak ("maptile::set_regiondata: palette must be arrayref");
2292    
2293     palette = SvRV (palette);
2294    
2295     STRLEN idxlen;
2296     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2297    
2298 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2299 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2300    
2301     for (int i = av_len ((AV *)palette) + 1; i--; )
2302 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2303 root 1.168
2304     for (int y = 0; y < THIS->height; ++y)
2305     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2306    
2307     sfree (THIS->regions, THIS->size ());
2308 root 1.230 delete [] THIS->regionmap;
2309 root 1.168
2310     THIS->regions = regions;
2311 root 1.156 THIS->regionmap = regionmap;
2312     }
2313    
2314 root 1.193 void
2315     maptile::create_region_treasure ()
2316     CODE:
2317     {
2318     object *op = object::create ();
2319     op->type = FLOOR;
2320     op->map = THIS;
2321    
2322     for (int x = 0; x < THIS->width; ++x)
2323     for (int y = 0; y < THIS->height; ++y)
2324     {
2325     region *rgn = THIS->region (x, y);
2326    
2327     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2328     if (rgn->treasure && rndm () < rgn->treasure_density)
2329     {
2330     op->x = x;
2331     op->y = y;
2332     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2333     }
2334     }
2335    
2336     op->destroy ();
2337     }
2338    
2339 root 1.74 int out_of_map (maptile *map, int x, int y)
2340    
2341 root 1.29 void
2342 root 1.61 trigger (maptile *map, long connection, bool state = true)
2343 root 1.29 CODE:
2344     activate_connection (map, connection, state);
2345    
2346     void
2347 root 1.61 get_connection (maptile *map, long connection)
2348 root 1.29 PPCODE:
2349     oblinkpt *obp = get_connection_links (map, connection);
2350     if (obp)
2351     for (objectlink *ol = obp->link; ol; ol = ol->next)
2352 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2353 root 1.29
2354 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2355 root 1.1
2356 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2357 root 1.1
2358 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2359 root 1.1 C_ARGS: str, map, nx, ny
2360    
2361     void
2362 root 1.140 get_map_flags (maptile *map, int x, int y)
2363 root 1.1 PPCODE:
2364     {
2365 root 1.61 maptile *nmap = 0;
2366 root 1.1 I16 nx = 0, ny = 0;
2367 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2368 root 1.1
2369     EXTEND (SP, 4);
2370     PUSHs (sv_2mortal (newSViv (flags)));
2371    
2372     if (GIMME_V == G_ARRAY)
2373     {
2374     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2375     PUSHs (sv_2mortal (newSViv (nx)));
2376     PUSHs (sv_2mortal (newSViv (ny)));
2377     }
2378     }
2379    
2380     void
2381 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2382 root 1.1 PROTOTYPE: $$$
2383     PPCODE:
2384     {
2385     object *o;
2386 root 1.61 maptile *nmap = 0;
2387 root 1.1 I16 nx, ny;
2388    
2389 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2390 root 1.1
2391     if (nmap)
2392     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2393     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2394     }
2395    
2396     SV *
2397 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2398 root 1.1 PROTOTYPE: $$$
2399     ALIAS:
2400     top_at = 1
2401     flags_at = 2
2402     light_at = 3
2403     move_block_at = 4
2404     move_slow_at = 5
2405     move_on_at = 6
2406     move_off_at = 7
2407     INIT:
2408 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2409 root 1.1 CODE:
2410     switch (ix)
2411     {
2412     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2413     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2414     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2415     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2416     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2417     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2418     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2419     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2420     }
2421 root 1.122 OUTPUT: RETVAL
2422 root 1.1
2423 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2424    
2425     void fix_walls_around (maptile *map, int x, int y)
2426 root 1.1
2427 root 1.117 # worst xs function of my life
2428 root 1.140 bool
2429 root 1.117 _create_random_map (\
2430 root 1.140 maptile *self,\
2431 root 1.183 utf8_string wallstyle,\
2432     utf8_string wall_name,\
2433     utf8_string floorstyle,\
2434     utf8_string monsterstyle,\
2435     utf8_string treasurestyle,\
2436     utf8_string layoutstyle,\
2437     utf8_string doorstyle,\
2438     utf8_string decorstyle,\
2439     utf8_string origin_map,\
2440     utf8_string final_map,\
2441     utf8_string exitstyle,\
2442     utf8_string this_map,\
2443     utf8_string exit_on_final_map,\
2444 root 1.146 int xsize,\
2445     int ysize,\
2446 root 1.117 int expand2x,\
2447     int layoutoptions1,\
2448     int layoutoptions2,\
2449     int layoutoptions3,\
2450     int symmetry,\
2451     int difficulty,\
2452     int difficulty_given,\
2453     float difficulty_increase,\
2454     int dungeon_level,\
2455     int dungeon_depth,\
2456     int decoroptions,\
2457     int orientation,\
2458     int origin_y,\
2459     int origin_x,\
2460 root 1.146 U32 random_seed,\
2461 root 1.117 val64 total_map_hp,\
2462     int map_layout_style,\
2463     int treasureoptions,\
2464     int symmetry_used,\
2465 root 1.137 region *region,\
2466 root 1.183 utf8_string custom\
2467 root 1.117 )
2468     CODE:
2469     {
2470     random_map_params rmp;
2471    
2472     assign (rmp.wallstyle , wallstyle);
2473     assign (rmp.wall_name , wall_name);
2474     assign (rmp.floorstyle , floorstyle);
2475     assign (rmp.monsterstyle , monsterstyle);
2476     assign (rmp.treasurestyle , treasurestyle);
2477     assign (rmp.layoutstyle , layoutstyle);
2478     assign (rmp.doorstyle , doorstyle);
2479     assign (rmp.decorstyle , decorstyle);
2480     assign (rmp.exitstyle , exitstyle);
2481     assign (rmp.exit_on_final_map, exit_on_final_map);
2482    
2483 root 1.122 rmp.origin_map = origin_map;
2484     rmp.final_map = final_map;
2485     rmp.this_map = this_map;
2486 root 1.146 rmp.xsize = xsize;
2487     rmp.ysize = ysize;
2488 root 1.117 rmp.expand2x = expand2x;
2489     rmp.layoutoptions1 = layoutoptions1;
2490     rmp.layoutoptions2 = layoutoptions2;
2491     rmp.layoutoptions3 = layoutoptions3;
2492     rmp.symmetry = symmetry;
2493     rmp.difficulty = difficulty;
2494     rmp.difficulty_given = difficulty_given;
2495     rmp.difficulty_increase = difficulty_increase;
2496     rmp.dungeon_level = dungeon_level;
2497     rmp.dungeon_depth = dungeon_depth;
2498     rmp.decoroptions = decoroptions;
2499     rmp.orientation = orientation;
2500     rmp.origin_y = origin_y;
2501     rmp.origin_x = origin_x;
2502     rmp.random_seed = random_seed;
2503 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2504 root 1.117 rmp.map_layout_style = map_layout_style;
2505     rmp.treasureoptions = treasureoptions;
2506     rmp.symmetry_used = symmetry_used;
2507     rmp.region = region;
2508 root 1.137 rmp.custom = custom;
2509 root 1.117
2510 root 1.140 RETVAL = self->generate_random_map (&rmp);
2511 root 1.117 }
2512     OUTPUT:
2513     RETVAL
2514    
2515 root 1.19 MODULE = cf PACKAGE = cf::arch
2516 root 1.1
2517 root 1.183 archetype *find (utf8_string name)
2518 elmex 1.36 CODE:
2519 root 1.60 RETVAL = archetype::find (name);
2520 elmex 1.36 OUTPUT:
2521     RETVAL
2522    
2523 root 1.218 int archetypes_size ()
2524     CODE:
2525     RETVAL = archetypes.size ();
2526     OUTPUT: RETVAL
2527    
2528     archetype *archetypes (U32 index)
2529     CODE:
2530     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2531     OUTPUT: RETVAL
2532 root 1.1
2533 root 1.212 object *instantiate (archetype *arch)
2534     CODE:
2535     RETVAL = arch_to_object (arch);
2536     OUTPUT:
2537     RETVAL
2538    
2539 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2540 root 1.1
2541 root 1.19 MODULE = cf PACKAGE = cf::party
2542 root 1.1
2543 root 1.19 partylist *first ()
2544 root 1.1 PROTOTYPE:
2545 root 1.19 CODE:
2546     RETVAL = get_firstparty ();
2547     OUTPUT: RETVAL
2548 root 1.1
2549 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2550 root 1.1
2551 root 1.19 MODULE = cf PACKAGE = cf::region
2552 root 1.1
2553 root 1.161 void
2554     list ()
2555     PPCODE:
2556     for_all_regions (rgn)
2557     XPUSHs (sv_2mortal (to_sv (rgn)));
2558    
2559 root 1.183 region *find (utf8_string name)
2560 root 1.161 PROTOTYPE: $
2561 root 1.19 CODE:
2562 root 1.161 RETVAL = region::find (name);
2563 root 1.19 OUTPUT: RETVAL
2564 root 1.1
2565 root 1.183 region *find_fuzzy (utf8_string name)
2566 root 1.122 PROTOTYPE: $
2567     CODE:
2568 root 1.161 RETVAL = region::find_fuzzy (name);
2569 root 1.122 OUTPUT: RETVAL
2570    
2571 root 1.186 int specificity (region *rgn)
2572     CODE:
2573     RETVAL = 0;
2574     while (rgn = rgn->parent)
2575     RETVAL++;
2576     OUTPUT: RETVAL
2577    
2578 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2579 root 1.1
2580 root 1.19 MODULE = cf PACKAGE = cf::living
2581 root 1.1
2582 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2583 root 1.1
2584 root 1.76 MODULE = cf PACKAGE = cf::settings
2585    
2586 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2587 root 1.76
2588 root 1.84 MODULE = cf PACKAGE = cf::client
2589 root 1.79
2590 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2591 root 1.79
2592 root 1.84 int invoke (client *ns, int event, ...)
2593 root 1.79 CODE:
2594 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2595 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2596     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2597 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2598 root 1.79 OUTPUT: RETVAL
2599    
2600 root 1.84 SV *registry (client *ns)
2601 root 1.79
2602 root 1.100 void
2603     list ()
2604     PPCODE:
2605     EXTEND (SP, clients.size ());
2606     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2607     PUSHs (sv_2mortal (to_sv (*i)));
2608    
2609 root 1.88 void
2610 root 1.100 client::send_packet (SV *packet)
2611     CODE:
2612     {
2613     STRLEN len;
2614     char *buf = SvPVbyte (packet, len);
2615    
2616     THIS->send_packet (buf, len);
2617     }
2618    
2619 root 1.237 faceidx
2620 root 1.238 client::need_face (utf8_string name, int pri = 0)
2621 root 1.237 CODE:
2622 root 1.238 RETVAL = face_find (name, 0);
2623     if (RETVAL)
2624     {
2625     THIS->send_face (RETVAL, pri);
2626     THIS->flush_fx ();
2627     }
2628     OUTPUT:
2629     RETVAL
2630    
2631     int
2632     client::fx_want (int idx, int value = -1)
2633     CODE:
2634     if (0 < idx && idx < FT_NUM)
2635     {
2636     RETVAL = THIS->fx_want [idx];
2637     if (items > 2)
2638     THIS->fx_want [idx] = value;
2639     }
2640     else
2641     RETVAL = 0;
2642 root 1.237 OUTPUT:
2643     RETVAL
2644    
2645 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2646    
2647     faceidx sound_find (utf8_string name)
2648    
2649 root 1.240 void sound_set (utf8_string str, faceidx face)
2650    
2651     # dire hack
2652     void old_sound_index (int idx, faceidx face)
2653     CODE:
2654     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2655     old_sound_index [idx] = face;
2656    
2657 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2658    
2659 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2660 root 1.176
2661 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2662 root 1.176
2663 root 1.183 faceidx alloc (utf8_string name)
2664 root 1.176 CODE:
2665     {
2666     do
2667     {
2668     RETVAL = faces.size ();
2669 root 1.177 faces.resize (RETVAL + 1);
2670 root 1.176 }
2671     while (!RETVAL); // crude way to leave index 0
2672    
2673     faces [RETVAL].name = name;
2674     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2675    
2676     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2677     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2678     }
2679     OUTPUT: RETVAL
2680    
2681 root 1.227 void set_type (faceidx idx, int value)
2682     ALIAS:
2683     set_type = 0
2684     set_visibility = 1
2685     set_magicmap = 2
2686     set_smooth = 3
2687     set_smoothlevel = 4
2688 root 1.176 CODE:
2689 root 1.229 faceinfo *f = face_info (idx); assert (f);
2690 root 1.227 switch (ix)
2691     {
2692     case 0: f->type = value; break;
2693     case 1: f->visibility = value; break;
2694     case 2: f->magicmap = value; break;
2695     case 3: f->smooth = value; break;
2696     case 4: f->smoothlevel = value; break;
2697     }
2698 root 1.177
2699     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2700 root 1.176 CODE:
2701 root 1.182 {
2702 root 1.231 faceinfo *f = face_info (idx); assert (f);
2703     facedata *d = &(faceset ? f->data64 : f->data32);
2704 root 1.181 sv_to (data, d->data);
2705     STRLEN clen;
2706     char *cdata = SvPVbyte (chksum, clen);
2707 root 1.182 clen = min (CHKSUM_SIZE, clen);
2708    
2709     if (memcmp (d->chksum, cdata, clen))
2710     {
2711     memcpy (d->chksum, cdata, clen);
2712    
2713     // invalidate existing client face info
2714     for_all_clients (ns)
2715     if (ns->faceset == faceset)
2716     {
2717     ns->faces_sent [idx] = false;
2718     ns->force_newmap = true;
2719     }
2720     }
2721     }
2722 root 1.176
2723 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2724     CODE:
2725     facedata *d = face_data (idx, faceset); assert (d);
2726     RETVAL = d->data.size ();
2727     OUTPUT:
2728     RETVAL
2729    
2730     SV *get_chksum (faceidx idx, int faceset = 0)
2731     CODE:
2732     facedata *d = face_data (idx, faceset); assert (d);
2733     RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2734     OUTPUT:
2735     RETVAL
2736    
2737 root 1.177 void invalidate (faceidx idx)
2738     CODE:
2739     for_all_clients (ns)
2740 root 1.182 {
2741     ns->faces_sent [idx] = false;
2742     ns->force_newmap = true;
2743     }
2744 root 1.177
2745     void invalidate_all ()
2746     CODE:
2747     for_all_clients (ns)
2748 root 1.182 {
2749     ns->faces_sent.reset ();
2750     ns->force_newmap = true;
2751     }
2752 root 1.177
2753 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2754    
2755     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2756    
2757     animidx anim_find (utf8_string name)
2758     CODE:
2759     RETVAL = animation::find (name).number;
2760     OUTPUT: RETVAL
2761    
2762     animidx set (utf8_string name, SV *frames, int facings = 1)
2763     CODE:
2764     {
2765     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2766     croak ("frames must be an arrayref");
2767    
2768     AV *av = (AV *)SvRV (frames);
2769    
2770     animation *anim = &animation::find (name);
2771     if (anim->number)
2772     {
2773     anim->resize (av_len (av) + 1);
2774     anim->facings = facings;
2775     }
2776     else
2777     anim = &animation::create (name, av_len (av) + 1, facings);
2778    
2779     for (int i = 0; i < anim->num_animations; ++i)
2780     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2781     }
2782     OUTPUT: RETVAL
2783    
2784     void invalidate_all ()
2785     CODE:
2786     for_all_clients (ns)
2787     ns->anims_sent.reset ();
2788