ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.320
Committed: Thu Jul 16 21:42:56 2009 UTC (14 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-2_80, rel-2_79
Changes since 1.319: +0 -1 lines
Log Message:
*** empty log message ***

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