ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.214
Committed: Sat May 26 15:44:07 2007 UTC (17 years ago) by root
Branch: MAIN
CVS Tags: rel-2_1
Changes since 1.213: +8 -5 lines
Log Message:
- restore after combined mainboard+harddisk crash
- cleanup/fixes for 2.1 release
- fix invoke to actually do work
- refactor invoke shortcuts, gcc cannot inline
  varargs functions.
- optimised invoke to 4-5 insns in the common case.
- optimised (For no good reason) the int-to-ascii
  conversions of dynbuf_text into division-less and
  branchless code (of which I am pretty proud).
- actually move players to their savebed when they did
  not use one and the map has been reste in the meantime.
  does not kill (yet) when too long.
- enter_map is now handled completely in perl.
- goto is now using generation counting to ensure that only the
  most-recently-issues goto will succeed.
- make some heavy use of __builtin_expect to streamline
  rare callbacks even more.
- optimised thawer.

File Contents

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