ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.319
Committed: Thu Jun 25 12:44:28 2009 UTC (14 years, 11 months ago) by elmex
Branch: MAIN
Changes since 1.318: +2 -0 lines
Log Message:
added ratelimited food table and made convert_item available to perl. and fixed manafountain.

File Contents

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