ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.223
Committed: Tue Jun 26 04:50:05 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.222: +10 -2 lines
Log Message:
shstr is utf-8

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