ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.216
Committed: Mon May 28 21:28:36 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.215: +21 -20 lines
Log Message:
update copyrights in server/*.C

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