ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.222
Committed: Sun Jun 24 04:09:29 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.221: +12 -0 lines
Log Message:
first rough cut of msg rewriting, introducing cfpod, a haxored pod variant for crossfire messgaes. where will it end?

File Contents

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