ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.220
Committed: Sat Jun 9 22:54:03 2007 UTC (16 years, 11 months ago) by root
Branch: MAIN
Changes since 1.219: +11 -11 lines
Log Message:
- introduce global NOW variable storing current tick time.
- force some packet send at least every 2 seconds, forcing
  an ack reply.
- timeout connections on ack delay exclusively, by default disconnect
  after 8 seconds (allowing for at least 5.5s of network hiccups).
  (linux only, should port to bsds).
- nuke ericserver stats code.
- reduce number of syscalls (less gettimeofday, only get tcp_info
  about once/second).
- get rid of coroapi.time () in favour of now ().

File Contents

# User Rev Content
1 root 1.1 /*
2 root 1.216 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3     *
4     * Copyright (©) 2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2001-2005,2007 by Chachkoff Yann
6     * Copyright (©) 2006,2007 by Marc Lehmann <cf@schmorp.de>
7     *
8     * Crossfire TRT is free software; you can redistribute it and/or modify it
9     * under the terms of the GNU General Public License as published by the Free
10     * Software Foundation; either version 2 of the License, or (at your option)
11     * any later version.
12     *
13     * This program is distributed in the hope that it will be useful, but
14     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16     * for more details.
17     *
18     * You should have received a copy of the GNU General Public License along
19     * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51
20     * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21     *
22     * The authors can be reached via e-mail to <crossfire@schmorp.de>
23 root 1.106 */
24 root 1.1
25 root 1.198 #include "autoconf.h"
26    
27 root 1.1 #define PLUGIN_NAME "perl"
28 root 1.13 #define PLUGIN_VERSION "cfperl 0.5"
29 root 1.1
30 root 1.189 #define CEDES_PER_TICK 5
31    
32 root 1.198 #if HAVE_EXECINFO_H
33     # include <execinfo.h>
34     #endif
35    
36 root 1.1 #include <plugin_common.h>
37     #include <sounds.h>
38 root 1.6 #include <cstdarg>
39     #include <sproto.h>
40 root 1.1
41 root 1.162 #include "loader.h"
42 root 1.6 #include "cfperl.h"
43 root 1.12 #include "shstr.h"
44 root 1.1
45 root 1.125 #include <unistd.h>
46     #if _POSIX_MEMLOCK
47     # include <sys/mman.h>
48     #endif
49    
50 root 1.32 #include <EXTERN.h>
51     #include <perl.h>
52     #include <XSUB.h>
53    
54 root 1.107 #include "CoroAPI.h"
55 root 1.1 #include "perlxsi.c"
56    
57     extern sint64 *levels; // the experience table
58    
59 root 1.61 typedef object object_ornull;
60     typedef maptile maptile_ornull;
61 root 1.1
62 root 1.183 typedef char *octet_string;
63     typedef char *utf8_string;
64     typedef const char *const_octet_string;
65     typedef const char *const_utf8_string;
66    
67 root 1.194 typedef std::string std__string;
68    
69 root 1.71 #if IVSIZE >= 8
70     typedef IV val64;
71     # define newSVval64 newSViv
72     # define SvVAL64 SvIV
73     #else
74     typedef double val64;
75     # define newSVval64 newSVnv
76     # define SvVAL64 SvNV
77     #endif
78 root 1.1
79 root 1.19 static f_plug_api gethook = cfapi_get_hooks;
80     static f_plug_api object_insert = cfapi_object_insert;
81 root 1.1
82     static PerlInterpreter *perl;
83    
84 root 1.220 tstamp NOW, runtime;
85 root 1.116
86 root 1.109 global gbl_ev;
87     static AV *cb_global, *cb_attachable, *cb_object, *cb_player, *cb_client, *cb_type, *cb_map;
88 root 1.189 static SV *sv_runtime, *sv_next_tick;
89 root 1.109
90 root 1.210 bitset<NUM_EVENT_TYPES> ev_want_event;
91     bitset<NUM_TYPES> ev_want_type;
92    
93 root 1.109 static HV
94     *stash_cf,
95     *stash_cf_object_wrap,
96     *stash_cf_object_player_wrap,
97     *stash_cf_player_wrap,
98     *stash_cf_map_wrap,
99     *stash_cf_client_wrap,
100     *stash_cf_arch_wrap,
101     *stash_cf_party_wrap,
102     *stash_cf_region_wrap,
103     *stash_cf_living_wrap;
104    
105     // helper cast function, returns super class * or 0
106     template<class super>
107     static super *
108     is_a (attachable *at)
109     {
110     //return dynamic_cast<super *>(at); // slower, safer
111     if (typeid (*at) == typeid (super))
112     return static_cast<super *>(at);
113     else
114     return 0;
115     }
116    
117     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118    
119     unordered_vector<attachable *> attachable::mortals;
120    
121 root 1.129 attachable::~attachable ()
122 root 1.109 {
123 root 1.133 assert (!self);
124 root 1.153 assert (!cb);
125 root 1.109 }
126    
127 root 1.130 int
128     attachable::refcnt_cnt () const
129     {
130 root 1.152 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
131 root 1.130 }
132    
133     void
134 root 1.155 attachable::sever_self ()
135 root 1.109 {
136 root 1.164 if (HV *self = this->self)
137 root 1.129 {
138 root 1.155 // keep a refcount because sv_unmagic might call attachable_free,
139     // which might clear self, causing sv_unmagic to crash on a now
140     // invalid object.
141 root 1.154 SvREFCNT_inc (self);
142 root 1.155 hv_clear (self);
143     sv_unmagic ((SV *)self, PERL_MAGIC_ext);
144 root 1.154 SvREFCNT_dec (self);
145 root 1.155
146     // self *must* be null now because thats sv_unmagic's job.
147 root 1.164 assert (!this->self);
148 root 1.129 }
149 root 1.109 }
150    
151 root 1.155 void
152     attachable::optimise ()
153     {
154     if (self
155     && SvREFCNT (self) == 1
156     && !HvTOTALKEYS (self))
157     sever_self ();
158     }
159    
160 root 1.109 // check wether the object really is dead
161     void
162     attachable::do_check ()
163     {
164 root 1.152 if (refcnt_cnt () > 0)
165 root 1.109 return;
166    
167 root 1.133 destroy ();
168 root 1.109 }
169    
170     void
171     attachable::do_destroy ()
172     {
173 root 1.214 INVOKE_ATTACHABLE (DESTROY, this);
174 root 1.109
175 root 1.153 if (cb)
176     {
177     SvREFCNT_dec (cb);
178     cb = 0;
179     }
180    
181 root 1.109 mortals.push_back (this);
182     }
183    
184     void
185     attachable::destroy ()
186     {
187     if (destroyed ())
188     return;
189    
190     flags |= F_DESTROYED;
191     do_destroy ();
192 root 1.198 sever_self ();
193 root 1.109 }
194    
195 root 1.130 void
196     attachable::check_mortals ()
197 root 1.109 {
198 root 1.150 static int i = 0;
199    
200     for (;;)
201 root 1.109 {
202 root 1.150 if (i >= mortals.size ())
203     {
204     i = 0;
205    
206     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.220 tstamp coroapi::next_cede;
1037 root 1.189
1038     void coroapi::do_cede_to_tick ()
1039     {
1040     cede_counter = 0;
1041    
1042     cede ();
1043    
1044     next_cede += (TICK / CEDES_PER_TICK) * 0.99;
1045     if (next_cede > SvNV (sv_next_tick) - 0.02)
1046     next_cede = SvNV (sv_next_tick);
1047     }
1048    
1049     void coroapi::do_cede_every ()
1050     {
1051     cede_counter = 0;
1052    
1053     if (coroapi::nready ())
1054     coroapi::cede ();
1055     }
1056    
1057     void coroapi::do_cede_to_tick_every ()
1058     {
1059     cede_counter = 0;
1060    
1061     cede_to_tick ();
1062     }
1063 root 1.124
1064 root 1.188 void
1065     coroapi::wait_for_tick ()
1066     {
1067     CALL_BEGIN (0);
1068     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1069     CALL_END;
1070     }
1071    
1072     void
1073     coroapi::wait_for_tick_begin ()
1074     {
1075     CALL_BEGIN (0);
1076     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1077     CALL_END;
1078     }
1079    
1080     static void
1081     iw_dispatch (pe_event *ev)
1082 root 1.85 {
1083     iw *w = (iw *)ev->ext_data;
1084     w->call (*w);
1085     }
1086    
1087     void
1088     iw::alloc ()
1089     {
1090     pe = GEventAPI->new_idle (0, 0);
1091    
1092 root 1.150 WaREENTRANT_off (pe);
1093 root 1.85 pe->base.callback = (void *)iw_dispatch;
1094     pe->base.ext_data = (void *)this;
1095     }
1096    
1097 root 1.80 static void iow_dispatch (pe_event *ev)
1098     {
1099     iow *w = (iow *)ev->ext_data;
1100     w->call (*w, ((pe_ioevent *)ev)->got);
1101     }
1102    
1103     void
1104     iow::alloc ()
1105     {
1106     pe = GEventAPI->new_io (0, 0);
1107    
1108 root 1.150 WaREENTRANT_off (pe);
1109 root 1.80 pe->base.callback = (void *)iow_dispatch;
1110     pe->base.ext_data = (void *)this;
1111    
1112 root 1.81 pe->fd = -1;
1113     pe->poll = 0;
1114 root 1.80 }
1115    
1116 root 1.85 void
1117 root 1.80 iow::fd (int fd)
1118     {
1119     pe->fd = fd;
1120     }
1121    
1122     int
1123     iow::poll ()
1124     {
1125     return pe->poll;
1126     }
1127    
1128 root 1.85 void
1129 root 1.80 iow::poll (int events)
1130     {
1131 root 1.81 if (pe->poll != events)
1132     {
1133     if (pe->poll) stop ();
1134     pe->poll = events;
1135     if (pe->poll) start ();
1136     }
1137 root 1.80 }
1138    
1139 root 1.109 void
1140     _connect_to_perl ()
1141     {
1142     stash_cf = gv_stashpv ("cf" , 1);
1143    
1144     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1145     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1146     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1147     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1148     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1149     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1150     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1151     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1152     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1153    
1154 root 1.189 sv_runtime = get_sv ("cf::RUNTIME" , 1); sv_upgrade (sv_runtime , SVt_NV);
1155     sv_next_tick = get_sv ("cf::NEXT_TICK", 1); sv_upgrade (sv_next_tick, SVt_NV);
1156 root 1.116
1157 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1158     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1159     cb_object = get_av ("cf::CB_OBJECT", 1);
1160     cb_player = get_av ("cf::CB_PLAYER", 1);
1161     cb_client = get_av ("cf::CB_CLIENT", 1);
1162     cb_type = get_av ("cf::CB_TYPE" , 1);
1163     cb_map = get_av ("cf::CB_MAP" , 1);
1164     }
1165    
1166 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1167    
1168     BOOT:
1169     {
1170 root 1.116 I_EVENT_API (PACKAGE); watcher_base::GEventAPI = GEventAPI;
1171     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1172 root 1.80
1173 root 1.189 _connect_to_perl ();
1174    
1175 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1176 root 1.63
1177 root 1.220 //{
1178     // require_pv ("Time::HiRes");
1179     //
1180     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1181     // if (!svp) croak ("Time::HiRes is required");
1182     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1183     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1184     //}
1185 root 1.189
1186 root 1.1 static const struct {
1187     const char *name;
1188     IV iv;
1189     } *civ, const_iv[] = {
1190     # define const_iv(name) { # name, (IV)name },
1191 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1192 root 1.198 const_iv (logBacktrace)
1193 root 1.180
1194 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1195    
1196     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1197 root 1.180
1198 root 1.5 const_iv (MAX_TIME)
1199 root 1.189
1200 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1201     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1202     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1203     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1204     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1205     const_iv (body_wrist) const_iv (body_waist)
1206 root 1.205
1207 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1208     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1209     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1210     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1211     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1212     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1213     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1214     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1215     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1216     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1217     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1218     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1219     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1220     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1221     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1222     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1223     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1224     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1225     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1226     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1227     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1228     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1229     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1230     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1231     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1232     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1233     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1234     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1235 root 1.1
1236 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1237 root 1.14
1238 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1239     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1240 root 1.1
1241 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1242     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1243     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1244     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1245     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1246     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1247     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1248    
1249     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1250     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1251 root 1.1 const_iv (WEAP_BLUD)
1252    
1253 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1254 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1255 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1256     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1257     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1258     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1259     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1260     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1261     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1262     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1263     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1264     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1265     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1266     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1267     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1268     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1269     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1270     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1271     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1272     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1273     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1274     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1275     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1276     const_iv (FLAG_OBJ_SAVE_ON_OVL) const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1277     const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1278     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1279    
1280     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1281     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1282     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1283     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1284 root 1.1 const_iv (NDI_ALL)
1285    
1286 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1287     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1288    
1289     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1290    
1291 root 1.212 const_iv (SP_RAISE_DEAD)
1292     const_iv (SP_RUNE)
1293     const_iv (SP_MAKE_MARK)
1294     const_iv (SP_BOLT)
1295     const_iv (SP_BULLET)
1296     const_iv (SP_EXPLOSION)
1297     const_iv (SP_CONE)
1298     const_iv (SP_BOMB)
1299     const_iv (SP_WONDER)
1300     const_iv (SP_SMITE)
1301     const_iv (SP_MAGIC_MISSILE)
1302     const_iv (SP_SUMMON_GOLEM)
1303     const_iv (SP_DIMENSION_DOOR)
1304     const_iv (SP_MAGIC_MAPPING)
1305     const_iv (SP_MAGIC_WALL)
1306     const_iv (SP_DESTRUCTION)
1307     const_iv (SP_PERCEIVE_SELF)
1308     const_iv (SP_WORD_OF_RECALL)
1309     const_iv (SP_INVISIBLE)
1310     const_iv (SP_PROBE)
1311     const_iv (SP_HEALING)
1312     const_iv (SP_CREATE_FOOD)
1313     const_iv (SP_EARTH_TO_DUST)
1314     const_iv (SP_CHANGE_ABILITY)
1315     const_iv (SP_BLESS)
1316     const_iv (SP_CURSE)
1317     const_iv (SP_SUMMON_MONSTER)
1318     const_iv (SP_CHARGING)
1319     const_iv (SP_POLYMORPH)
1320     const_iv (SP_ALCHEMY)
1321     const_iv (SP_REMOVE_CURSE)
1322     const_iv (SP_IDENTIFY)
1323     const_iv (SP_DETECTION)
1324     const_iv (SP_MOOD_CHANGE)
1325     const_iv (SP_MOVING_BALL)
1326     const_iv (SP_SWARM)
1327     const_iv (SP_CHANGE_MANA)
1328     const_iv (SP_DISPEL_RUNE)
1329     const_iv (SP_CREATE_MISSILE)
1330     const_iv (SP_CONSECRATE)
1331     const_iv (SP_ANIMATE_WEAPON)
1332     const_iv (SP_LIGHT)
1333     const_iv (SP_CHANGE_MAP_LIGHT)
1334     const_iv (SP_FAERY_FIRE)
1335     const_iv (SP_CAUSE_DISEASE)
1336     const_iv (SP_AURA)
1337     const_iv (SP_TOWN_PORTAL)
1338     const_iv (SP_PARTY_SPELL)
1339    
1340 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1341     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1342 root 1.1 const_iv (F_LOCKED)
1343    
1344 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1345    
1346     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1347     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1348    
1349     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1350    
1351     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1352     const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR) const_iv (INS_MAP_LOAD)
1353    
1354     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1355     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1356    
1357     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1358    
1359     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1360     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1361     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1362     const_iv (M_ICE) const_iv (M_SPECIAL)
1363    
1364     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1365     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1366    
1367     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1368     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1369     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1370     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1371     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1372     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1373     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1374     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1375     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1376     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1377 root 1.1 const_iv (SK_POISON_NAIL)
1378    
1379 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1380     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1381     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1382     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1383     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1384     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1385    
1386     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1387    
1388     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1389     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1390     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1391     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1392     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1393     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1394     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1395    
1396     const_iv (MAP_IN_MEMORY) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1397    
1398     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1399     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1400    
1401     const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1402    
1403     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1404 root 1.99
1405 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1406 root 1.117
1407     // random map generator
1408 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1409     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1410    
1411     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1412     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1413     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1414    
1415     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1416     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1417 root 1.195
1418     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1419     const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_UPDATE_INV)
1420     const_iv (GT_MINIMAL)
1421 root 1.1 };
1422    
1423     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1424 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1425 root 1.1
1426     static const struct {
1427     const char *name;
1428 root 1.14 int skip;
1429 root 1.7 IV klass;
1430 root 1.1 IV iv;
1431 root 1.6 } *eiv, event_iv[] = {
1432 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1433 root 1.6 # include "eventinc.h"
1434     # undef def
1435     };
1436    
1437     AV *av = get_av ("cf::EVENT", 1);
1438    
1439     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1440 root 1.7 {
1441     AV *event = newAV ();
1442 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1443 root 1.7 av_push (event, newSViv (eiv->klass));
1444     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1445 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1446 root 1.7 }
1447 root 1.14 }
1448    
1449 root 1.109 void _connect_to_perl ()
1450 root 1.14
1451 root 1.210 void _recalc_want ()
1452    
1453 root 1.47 void _global_reattach ()
1454 root 1.14 CODE:
1455     {
1456     // reattach to all attachable objects in the game.
1457 root 1.128 for_all_clients (ns)
1458     ns->reattach ();
1459 root 1.96
1460 root 1.128 for_all_objects (op)
1461 root 1.109 op->reattach ();
1462 root 1.1 }
1463    
1464 root 1.189 void _post_tick ()
1465     CODE:
1466     coroapi::next_cede = SvNV (sv_next_tick) - TICK * (1. - 1. / CEDES_PER_TICK);
1467    
1468 root 1.192 # support function for map-world.ext
1469     void _quantise (SV *data_sv, SV *plt_sv)
1470     CODE:
1471     {
1472     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1473     croak ("_quantise called with invalid agruments");
1474    
1475     plt_sv = SvRV (plt_sv);
1476     SV **plt = AvARRAY (plt_sv);
1477     int plt_count = AvFILL (plt_sv) + 1;
1478    
1479     STRLEN len;
1480     char *data = SvPVbyte (data_sv, len);
1481     char *dst = data;
1482    
1483     while (len >= 3)
1484     {
1485     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1486     {
1487     char *val = SvPVX (*val_sv);
1488    
1489     if (val [0] == data [0]
1490     && val [1] == data [1]
1491     && val [2] == data [2])
1492     {
1493     *dst++ = val [3];
1494     goto next;
1495     }
1496     }
1497    
1498     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1499     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1500     dst - SvPVX (data_sv), len);
1501    
1502     next:
1503     data += 3;
1504     len -= 3;
1505     }
1506    
1507     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1508     }
1509    
1510 root 1.1 NV floor (NV x)
1511    
1512     NV ceil (NV x)
1513    
1514 root 1.143 NV rndm (...)
1515     CODE:
1516     switch (items)
1517     {
1518     case 0: RETVAL = rndm (); break;
1519     case 1: RETVAL = rndm (SvUV (ST (0))); break;
1520     case 2: RETVAL = rndm (SvIV (ST (0)), SvIV (ST (1))); break;
1521     default: croak ("cf::rndm requires none, one or two parameters."); break;
1522     }
1523     OUTPUT:
1524     RETVAL
1525    
1526 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1527     CODE:
1528     RETVAL = clamp (value, min_value, max_value);
1529     OUTPUT:
1530     RETVAL
1531    
1532     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1533     CODE:
1534     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1535     OUTPUT:
1536     RETVAL
1537    
1538     void cede_to_tick ()
1539     CODE:
1540     coroapi::cede_to_tick ();
1541    
1542 root 1.5 void server_tick ()
1543 root 1.116 CODE:
1544 root 1.220 NOW = now ();
1545 root 1.116 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.215 const char *slot_use_name (U32 slot)
1747 root 1.205 ALIAS:
1748 root 1.215 slot_nonuse_name = 1
1749 root 1.205 CODE:
1750     {
1751     if (slot >= NUM_BODY_LOCATIONS)
1752     croak ("body slot index out of range");
1753    
1754     switch (ix)
1755     {
1756 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1757     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1758 root 1.205 }
1759     }
1760     OUTPUT:
1761     RETVAL
1762    
1763 root 1.1 # missing properties
1764    
1765 root 1.54 object *head (object *op)
1766     PROTOTYPE: $
1767     CODE:
1768 root 1.134 RETVAL = op->head_ ();
1769 root 1.54 OUTPUT: RETVAL
1770    
1771 root 1.1 void
1772     inv (object *obj)
1773     PROTOTYPE: $
1774     PPCODE:
1775     {
1776     object *o;
1777     for (o = obj->inv; o; o = o->below)
1778 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1779 root 1.1 }
1780    
1781 root 1.102 void
1782     set_animation (object *op, int idx)
1783     CODE:
1784     SET_ANIMATION (op, idx);
1785    
1786 elmex 1.160 int
1787     num_animations (object *op)
1788     CODE:
1789     RETVAL = NUM_ANIMATIONS (op);
1790     OUTPUT: RETVAL
1791    
1792 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1793     ALIAS:
1794     slot_used = 1
1795     CODE:
1796     {
1797     if (slot >= NUM_BODY_LOCATIONS)
1798     croak ("body slot index out of range");
1799    
1800 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1801 root 1.205
1802     if (items > 2)
1803     if (ix)
1804 root 1.208 op->slot[slot].used = value;
1805     else
1806 root 1.205 op->slot[slot].info = value;
1807     }
1808     OUTPUT:
1809     RETVAL
1810    
1811 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1812 root 1.58
1813     object *find_marked_object (object *op)
1814    
1815 root 1.109 int need_identify (object *obj);
1816 root 1.1
1817     int apply_shop_mat (object *shop_mat, object *op);
1818    
1819 pippijn 1.172 int move_player (object *op, int dir)
1820     CODE:
1821     RETVAL = move_player (op, dir);
1822     OUTPUT:
1823     RETVAL
1824    
1825 root 1.27 int move (object *op, int dir, object *originator = op)
1826     CODE:
1827     RETVAL = move_ob (op, dir, originator);
1828     OUTPUT:
1829     RETVAL
1830 root 1.1
1831 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1832     CODE:
1833     manual_apply (applied, applier, flags);
1834 root 1.1
1835 root 1.74 void apply_below (object *op)
1836     CODE:
1837     player_apply_below (op);
1838 root 1.1
1839 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
1840    
1841 root 1.183 object *cf_object_present_archname_inside (object *op, utf8_string whatstr)
1842 root 1.1
1843     int cf_object_transfer (object *op, int x, int y, int r = 0, object_ornull *orig = 0)
1844    
1845 root 1.61 int cf_object_change_map (object *op, int x, int y, maptile *map)
1846 root 1.1
1847 root 1.116 #//TODO
1848     object *clone_ (object *op, int recursive = 0)
1849 root 1.74 CODE:
1850     if (recursive)
1851     RETVAL = object_create_clone (op);
1852     else
1853     {
1854     RETVAL = object::create ();
1855 root 1.75 op->copy_to (RETVAL);
1856 root 1.74 }
1857     OUTPUT: RETVAL
1858 root 1.1
1859 root 1.74 int pay_item (object *op, object *buyer)
1860     CODE:
1861     RETVAL = pay_for_item (op, buyer);
1862     OUTPUT: RETVAL
1863 root 1.1
1864 root 1.74 int pay_amount (object *op, uint64 amount)
1865     CODE:
1866     RETVAL = pay_for_amount (amount, op);
1867     OUTPUT: RETVAL
1868 root 1.1
1869     void pay_player (object *op, uint64 amount)
1870    
1871 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
1872 root 1.1
1873 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
1874 root 1.1
1875 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
1876     CODE:
1877     do_learn_spell (op, sp, special_prayer);
1878 root 1.1
1879 root 1.74 void forget_spell (object *op, object *sp)
1880     CODE:
1881     do_forget_spell (op, query_name (sp));
1882 root 1.1
1883 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
1884 root 1.74 CODE:
1885     RETVAL = check_spell_known (op, spellname);
1886     OUTPUT: RETVAL
1887 root 1.1
1888 root 1.74 int query_money (object *op)
1889 root 1.1 ALIAS: money = 0
1890    
1891 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
1892 root 1.1 ALIAS: cost = 0
1893    
1894 root 1.74 void spring_trap (object *op, object *victim)
1895 root 1.1
1896 root 1.74 int check_trigger (object *op, object *cause)
1897 root 1.1
1898 root 1.74 void drop (object *who, object *op)
1899 root 1.1
1900 root 1.74 void pick_up (object *who, object *op)
1901 root 1.1
1902 root 1.61 int cf_object_teleport (object *op, maptile *map, int x, int y)
1903 root 1.1
1904 root 1.102 void update_object (object *op, int action)
1905 root 1.1
1906 root 1.183 object *cf_create_object_by_name (utf8_string name)
1907 root 1.1
1908 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
1909 root 1.1
1910     void player_lvl_adj (object *who, object *skill = 0)
1911    
1912     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
1913    
1914     int calc_skill_exp (object *who, object *op, object *skill);
1915    
1916     void push_button (object *op);
1917    
1918     void use_trigger (object *op);
1919    
1920 root 1.61 void add_button_link (object *button, maptile *map, int connected);
1921 root 1.1
1922     void remove_button_link (object *op);
1923    
1924    
1925     MODULE = cf PACKAGE = cf::object PREFIX = cf_
1926    
1927     object *cf_insert_ob_in_ob (object *ob, object *where)
1928    
1929     # no clean way to get an object from an archetype - stupid idiotic
1930     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
1931    
1932 root 1.183 object *new (utf8_string archetype = 0)
1933 root 1.1 PROTOTYPE: ;$
1934     CODE:
1935 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
1936 root 1.1 OUTPUT:
1937     RETVAL
1938    
1939 root 1.218 # TODO: nuke
1940 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
1941 root 1.1 PROTOTYPE: $$$$$$
1942     CODE:
1943     {
1944     int unused_type;
1945     RETVAL = (object *)object_insert (&unused_type, ob, 0, where, orig, flag, x, y);
1946     }
1947    
1948     player *contr (object *op)
1949     CODE:
1950     RETVAL = op->contr;
1951     OUTPUT: RETVAL
1952    
1953 root 1.183 const_utf8_string get_ob_key_value (object *op, utf8_string key)
1954 root 1.1
1955 root 1.183 bool set_ob_key_value (object *op, utf8_string key, utf8_string value = 0, int add_key = 1)
1956 root 1.1
1957     object *get_nearest_player (object *ob)
1958     ALIAS: nearest_player = 0
1959     PREINIT:
1960     extern object *get_nearest_player (object *);
1961    
1962     void rangevector (object *ob, object *other, int flags = 0)
1963     PROTOTYPE: $$;$
1964     PPCODE:
1965     {
1966     rv_vector rv;
1967     get_rangevector (ob, other, &rv, flags);
1968     EXTEND (SP, 5);
1969     PUSHs (newSVuv (rv.distance));
1970     PUSHs (newSViv (rv.distance_x));
1971     PUSHs (newSViv (rv.distance_y));
1972     PUSHs (newSViv (rv.direction));
1973     PUSHs (newSVcfapi (CFAPI_POBJECT, rv.part));
1974     }
1975    
1976     bool on_same_map_as (object *ob, object *other)
1977     CODE:
1978     RETVAL = on_same_map (ob, other);
1979     OUTPUT: RETVAL
1980    
1981 root 1.183 const_utf8_string
1982 root 1.58 base_name (object *op, int plural = op->nrof > 1)
1983 root 1.1 CODE:
1984 root 1.58 RETVAL = query_base_name (op, plural);
1985 root 1.1 OUTPUT: RETVAL
1986    
1987 elmex 1.86 object *decrease_ob_nr (object *op, unsigned long i)
1988    
1989 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
1990    
1991     player *player (object *op)
1992     CODE:
1993     RETVAL = op->contr;
1994     OUTPUT: RETVAL
1995    
1996 root 1.105 void check_score (object *op)
1997    
1998 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
1999 root 1.120 CODE:
2000     new_draw_info (flags, 0, op, txt);
2001 root 1.1
2002     void kill_player (object *op)
2003    
2004 root 1.58 void esrv_update_item (object *op, int what, object *item)
2005     C_ARGS: what, op, item
2006    
2007 root 1.183 int command_summon (object *op, utf8_string params)
2008 root 1.67
2009 root 1.183 int command_arrest (object *op, utf8_string params)
2010 root 1.67
2011 root 1.66
2012 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2013 root 1.1
2014 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2015 root 1.62
2016 root 1.18 int invoke (player *pl, int event, ...)
2017     CODE:
2018     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2019 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2020     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2021 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2022 root 1.18 OUTPUT: RETVAL
2023    
2024 root 1.12 SV *registry (player *pl)
2025 root 1.1
2026 root 1.102 void
2027     save_stats (player *pl)
2028     CODE:
2029     pl->ob->stats.hp = pl->ob->stats.maxhp;
2030     pl->ob->stats.sp = pl->ob->stats.maxsp;
2031     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2032     pl->orig_stats = pl->ob->stats;
2033    
2034 root 1.217 void clear_los (player *pl)
2035    
2036 root 1.1 void cf_player_move (player *pl, int dir)
2037    
2038     void play_sound_player_only (player *pl, int soundnum, int x = 0, int y = 0);
2039    
2040     bool
2041     cell_visible (player *pl, int dx, int dy)
2042     CODE:
2043 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2044     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2045 root 1.1 OUTPUT:
2046     RETVAL
2047    
2048 root 1.4 void
2049 root 1.1 send (player *pl, SV *packet)
2050     CODE:
2051     {
2052     STRLEN len;
2053     char *buf = SvPVbyte (packet, len);
2054    
2055 root 1.100 if (pl->ns)
2056     pl->ns->send_packet (buf, len);
2057 root 1.1 }
2058    
2059     int
2060     listening (player *pl, int new_value = -1)
2061     CODE:
2062     RETVAL = pl->listening;
2063     if (new_value >= 0)
2064     pl->listening = new_value;
2065     OUTPUT:
2066     RETVAL
2067    
2068 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2069 root 1.45 PROTOTYPE: $;$$$
2070 root 1.1 PPCODE:
2071 root 1.45 if (GIMME_V != G_VOID)
2072     {
2073     EXTEND (SP, 3);
2074     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2075     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2076     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2077     }
2078 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2079     if (x) sv_to (x, pl->bed_x);
2080     if (y) sv_to (y, pl->bed_y);
2081 root 1.1
2082     void
2083     list ()
2084     PPCODE:
2085 root 1.128 for_all_players (pl)
2086 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2087 root 1.1
2088    
2089     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2090    
2091 root 1.61 int invoke (maptile *map, int event, ...)
2092 root 1.18 CODE:
2093     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2094 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2095     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2096 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2097 root 1.25 OUTPUT: RETVAL
2098 root 1.18
2099 root 1.61 SV *registry (maptile *map)
2100 root 1.12
2101 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2102 root 1.1
2103 root 1.116 void
2104     maptile::instantiate ()
2105    
2106     maptile *new ()
2107 root 1.1 PROTOTYPE:
2108     CODE:
2109 root 1.116 RETVAL = new maptile;
2110 root 1.1 OUTPUT:
2111     RETVAL
2112    
2113 root 1.116 void
2114 root 1.117 maptile::players ()
2115     PPCODE:
2116     if (GIMME_V == G_SCALAR)
2117 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2118 root 1.117 else if (GIMME_V == G_ARRAY)
2119     {
2120     EXTEND (SP, THIS->players);
2121     for_all_players (pl)
2122     if (pl->ob && pl->ob->map == THIS)
2123 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2124 root 1.117 }
2125    
2126 root 1.156 void
2127 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2128 root 1.156 CODE:
2129     {
2130 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2131     croak ("maptile::add_underlay: palette must be arrayref");
2132 root 1.156
2133 root 1.168 palette = SvRV (palette);
2134 root 1.156
2135 root 1.168 STRLEN idxlen;
2136     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2137 root 1.156
2138 root 1.168 for (int x = 0; x < THIS->width; ++x)
2139     for (int y = 0; y < THIS->height; ++y)
2140     {
2141     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2142     if (op->flag [FLAG_IS_FLOOR])
2143     goto skip_space;
2144    
2145     {
2146     int offs = offset + y * stride + x;
2147     if (IN_RANGE_EXC (offs, 0, idxlen))
2148     {
2149     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2150     {
2151     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2152     ob->flag [FLAG_NO_MAP_SAVE] = true;
2153     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2154 root 1.200
2155     if (ob->randomitems)
2156     {
2157 root 1.203 if (!ob->above)
2158     {
2159     ob->create_treasure (ob->randomitems);
2160    
2161     for (object *op = ob->above; op; op = op->above)
2162     op->flag [FLAG_NO_MAP_SAVE] = true;
2163     }
2164    
2165 root 1.200 ob->randomitems = 0;
2166     }
2167 root 1.168 }
2168     }
2169     }
2170 root 1.156
2171 root 1.168 skip_space: ;
2172     }
2173     }
2174    
2175     void
2176     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2177     CODE:
2178     {
2179     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2180     croak ("maptile::set_regiondata: palette must be arrayref");
2181    
2182     palette = SvRV (palette);
2183    
2184     STRLEN idxlen;
2185     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2186    
2187     region **regionmap = (region **)malloc (
2188     (av_len ((AV *)palette) + 1) * sizeof (region *));
2189     uint8_t *regions = salloc<uint8_t> (THIS->size ());
2190    
2191     for (int i = av_len ((AV *)palette) + 1; i--; )
2192     regionmap [i] = region::find (
2193     SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2194    
2195     for (int y = 0; y < THIS->height; ++y)
2196     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2197    
2198     sfree (THIS->regions, THIS->size ());
2199     free (THIS->regionmap);
2200    
2201     THIS->regions = regions;
2202 root 1.156 THIS->regionmap = regionmap;
2203     }
2204    
2205 root 1.193 void
2206     maptile::create_region_treasure ()
2207     CODE:
2208     {
2209     object *op = object::create ();
2210     op->type = FLOOR;
2211     op->map = THIS;
2212    
2213     for (int x = 0; x < THIS->width; ++x)
2214     for (int y = 0; y < THIS->height; ++y)
2215     {
2216     region *rgn = THIS->region (x, y);
2217    
2218     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2219     if (rgn->treasure && rndm () < rgn->treasure_density)
2220     {
2221     op->x = x;
2222     op->y = y;
2223     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2224     }
2225     }
2226    
2227     op->destroy ();
2228     }
2229    
2230 root 1.61 void play_sound_map (maptile *map, int x, int y, int sound_num)
2231 root 1.1
2232 root 1.74 int out_of_map (maptile *map, int x, int y)
2233    
2234 root 1.29 void
2235 root 1.61 trigger (maptile *map, long connection, bool state = true)
2236 root 1.29 CODE:
2237     activate_connection (map, connection, state);
2238    
2239     void
2240 root 1.61 get_connection (maptile *map, long connection)
2241 root 1.29 PPCODE:
2242     oblinkpt *obp = get_connection_links (map, connection);
2243     if (obp)
2244     for (objectlink *ol = obp->link; ol; ol = ol->next)
2245 root 1.65 XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, (object *)ol->ob)));
2246 root 1.29
2247 root 1.61 object *cf_map_insert_object_there (maptile *where, object *op, object *originator, int flags)
2248 root 1.1
2249 root 1.61 object *cf_map_insert_object (maptile *where, object* op, int x, int y)
2250 root 1.1
2251 root 1.61 object* cf_map_present_arch_by_name (maptile *map, const char* str, int nx, int ny)
2252 root 1.1 C_ARGS: str, map, nx, ny
2253    
2254     void
2255 root 1.140 get_map_flags (maptile *map, int x, int y)
2256 root 1.1 PPCODE:
2257     {
2258 root 1.61 maptile *nmap = 0;
2259 root 1.1 I16 nx = 0, ny = 0;
2260 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2261 root 1.1
2262     EXTEND (SP, 4);
2263     PUSHs (sv_2mortal (newSViv (flags)));
2264    
2265     if (GIMME_V == G_ARRAY)
2266     {
2267     PUSHs (sv_2mortal (newSVcfapi (CFAPI_PMAP, nmap)));
2268     PUSHs (sv_2mortal (newSViv (nx)));
2269     PUSHs (sv_2mortal (newSViv (ny)));
2270     }
2271     }
2272    
2273     void
2274 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2275 root 1.1 PROTOTYPE: $$$
2276     PPCODE:
2277     {
2278     object *o;
2279 root 1.61 maptile *nmap = 0;
2280 root 1.1 I16 nx, ny;
2281    
2282 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2283 root 1.1
2284     if (nmap)
2285     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2286     XPUSHs (sv_2mortal (newSVcfapi (CFAPI_POBJECT, o)));
2287     }
2288    
2289     SV *
2290 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2291 root 1.1 PROTOTYPE: $$$
2292     ALIAS:
2293     top_at = 1
2294     flags_at = 2
2295     light_at = 3
2296     move_block_at = 4
2297     move_slow_at = 5
2298     move_on_at = 6
2299     move_off_at = 7
2300     INIT:
2301 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2302 root 1.1 CODE:
2303     switch (ix)
2304     {
2305     case 0: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_OB (obj, x, y)); break;
2306     case 1: RETVAL = newSVcfapi (CFAPI_POBJECT, GET_MAP_TOP (obj, x, y)); break;
2307     case 2: RETVAL = newSVuv ( GET_MAP_FLAGS (obj, x, y)); break;
2308     case 3: RETVAL = newSViv ( GET_MAP_LIGHT (obj, x, y)); break;
2309     case 4: RETVAL = newSVuv ( GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2310     case 5: RETVAL = newSVuv ( GET_MAP_MOVE_SLOW (obj, x, y)); break;
2311     case 6: RETVAL = newSVuv ( GET_MAP_MOVE_ON (obj, x, y)); break;
2312     case 7: RETVAL = newSVuv ( GET_MAP_MOVE_OFF (obj, x, y)); break;
2313     }
2314 root 1.122 OUTPUT: RETVAL
2315 root 1.1
2316 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2317    
2318     void fix_walls_around (maptile *map, int x, int y)
2319 root 1.1
2320 root 1.117 # worst xs function of my life
2321 root 1.140 bool
2322 root 1.117 _create_random_map (\
2323 root 1.140 maptile *self,\
2324 root 1.183 utf8_string wallstyle,\
2325     utf8_string wall_name,\
2326     utf8_string floorstyle,\
2327     utf8_string monsterstyle,\
2328     utf8_string treasurestyle,\
2329     utf8_string layoutstyle,\
2330     utf8_string doorstyle,\
2331     utf8_string decorstyle,\
2332     utf8_string origin_map,\
2333     utf8_string final_map,\
2334     utf8_string exitstyle,\
2335     utf8_string this_map,\
2336     utf8_string exit_on_final_map,\
2337 root 1.146 int xsize,\
2338     int ysize,\
2339 root 1.117 int expand2x,\
2340     int layoutoptions1,\
2341     int layoutoptions2,\
2342     int layoutoptions3,\
2343     int symmetry,\
2344     int difficulty,\
2345     int difficulty_given,\
2346     float difficulty_increase,\
2347     int dungeon_level,\
2348     int dungeon_depth,\
2349     int decoroptions,\
2350     int orientation,\
2351     int origin_y,\
2352     int origin_x,\
2353 root 1.146 U32 random_seed,\
2354 root 1.117 val64 total_map_hp,\
2355     int map_layout_style,\
2356     int treasureoptions,\
2357     int symmetry_used,\
2358 root 1.137 region *region,\
2359 root 1.183 utf8_string custom\
2360 root 1.117 )
2361     CODE:
2362     {
2363     random_map_params rmp;
2364    
2365     assign (rmp.wallstyle , wallstyle);
2366     assign (rmp.wall_name , wall_name);
2367     assign (rmp.floorstyle , floorstyle);
2368     assign (rmp.monsterstyle , monsterstyle);
2369     assign (rmp.treasurestyle , treasurestyle);
2370     assign (rmp.layoutstyle , layoutstyle);
2371     assign (rmp.doorstyle , doorstyle);
2372     assign (rmp.decorstyle , decorstyle);
2373     assign (rmp.exitstyle , exitstyle);
2374     assign (rmp.exit_on_final_map, exit_on_final_map);
2375    
2376 root 1.122 rmp.origin_map = origin_map;
2377     rmp.final_map = final_map;
2378     rmp.this_map = this_map;
2379 root 1.146 rmp.xsize = xsize;
2380     rmp.ysize = ysize;
2381 root 1.117 rmp.expand2x = expand2x;
2382     rmp.layoutoptions1 = layoutoptions1;
2383     rmp.layoutoptions2 = layoutoptions2;
2384     rmp.layoutoptions3 = layoutoptions3;
2385     rmp.symmetry = symmetry;
2386     rmp.difficulty = difficulty;
2387     rmp.difficulty_given = difficulty_given;
2388     rmp.difficulty_increase = difficulty_increase;
2389     rmp.dungeon_level = dungeon_level;
2390     rmp.dungeon_depth = dungeon_depth;
2391     rmp.decoroptions = decoroptions;
2392     rmp.orientation = orientation;
2393     rmp.origin_y = origin_y;
2394     rmp.origin_x = origin_x;
2395     rmp.random_seed = random_seed;
2396 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2397 root 1.117 rmp.map_layout_style = map_layout_style;
2398     rmp.treasureoptions = treasureoptions;
2399     rmp.symmetry_used = symmetry_used;
2400     rmp.region = region;
2401 root 1.137 rmp.custom = custom;
2402 root 1.117
2403 root 1.140 RETVAL = self->generate_random_map (&rmp);
2404 root 1.117 }
2405     OUTPUT:
2406     RETVAL
2407    
2408 root 1.19 MODULE = cf PACKAGE = cf::arch
2409 root 1.1
2410 root 1.183 archetype *find (utf8_string name)
2411 elmex 1.36 CODE:
2412 root 1.60 RETVAL = archetype::find (name);
2413 elmex 1.36 OUTPUT:
2414     RETVAL
2415    
2416 root 1.218 int archetypes_size ()
2417     CODE:
2418     RETVAL = archetypes.size ();
2419     OUTPUT: RETVAL
2420    
2421     archetype *archetypes (U32 index)
2422     CODE:
2423     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2424     OUTPUT: RETVAL
2425 root 1.1
2426 root 1.212 object *instantiate (archetype *arch)
2427     CODE:
2428     RETVAL = arch_to_object (arch);
2429     OUTPUT:
2430     RETVAL
2431    
2432 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2433 root 1.1
2434 root 1.19 MODULE = cf PACKAGE = cf::party
2435 root 1.1
2436 root 1.19 partylist *first ()
2437 root 1.1 PROTOTYPE:
2438 root 1.19 CODE:
2439     RETVAL = get_firstparty ();
2440     OUTPUT: RETVAL
2441 root 1.1
2442 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2443 root 1.1
2444 root 1.19 MODULE = cf PACKAGE = cf::region
2445 root 1.1
2446 root 1.161 void
2447     list ()
2448     PPCODE:
2449     for_all_regions (rgn)
2450     XPUSHs (sv_2mortal (to_sv (rgn)));
2451    
2452 root 1.183 region *find (utf8_string name)
2453 root 1.161 PROTOTYPE: $
2454 root 1.19 CODE:
2455 root 1.161 RETVAL = region::find (name);
2456 root 1.19 OUTPUT: RETVAL
2457 root 1.1
2458 root 1.183 region *find_fuzzy (utf8_string name)
2459 root 1.122 PROTOTYPE: $
2460     CODE:
2461 root 1.161 RETVAL = region::find_fuzzy (name);
2462 root 1.122 OUTPUT: RETVAL
2463    
2464 root 1.186 int specificity (region *rgn)
2465     CODE:
2466     RETVAL = 0;
2467     while (rgn = rgn->parent)
2468     RETVAL++;
2469     OUTPUT: RETVAL
2470    
2471 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2472 root 1.1
2473 root 1.19 MODULE = cf PACKAGE = cf::living
2474 root 1.1
2475 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2476 root 1.1
2477 root 1.76 MODULE = cf PACKAGE = cf::settings
2478    
2479 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2480 root 1.76
2481 root 1.84 MODULE = cf PACKAGE = cf::client
2482 root 1.79
2483 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2484 root 1.79
2485 root 1.84 int invoke (client *ns, int event, ...)
2486 root 1.79 CODE:
2487 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2488 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2489     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2490 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2491 root 1.79 OUTPUT: RETVAL
2492    
2493 root 1.84 SV *registry (client *ns)
2494 root 1.79
2495 root 1.100 void
2496     list ()
2497     PPCODE:
2498     EXTEND (SP, clients.size ());
2499     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2500     PUSHs (sv_2mortal (to_sv (*i)));
2501    
2502 root 1.88 void
2503 root 1.100 client::send_packet (SV *packet)
2504     CODE:
2505     {
2506     STRLEN len;
2507     char *buf = SvPVbyte (packet, len);
2508    
2509     THIS->send_packet (buf, len);
2510     }
2511    
2512 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2513    
2514 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2515 root 1.176
2516 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2517 root 1.176
2518 root 1.183 faceidx alloc (utf8_string name)
2519 root 1.176 CODE:
2520     {
2521     do
2522     {
2523     RETVAL = faces.size ();
2524 root 1.177 faces.resize (RETVAL + 1);
2525 root 1.176 }
2526     while (!RETVAL); // crude way to leave index 0
2527    
2528     faces [RETVAL].name = name;
2529     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2530    
2531     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2532     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2533     }
2534     OUTPUT: RETVAL
2535    
2536 root 1.177 void set (faceidx idx, int visibility, int magicmap)
2537 root 1.176 CODE:
2538 root 1.177 faceinfo *f = face_info (idx);
2539     assert (f);
2540     f->visibility = visibility;
2541     f->magicmap = magicmap;
2542 root 1.176
2543 root 1.184 void set_smooth (faceidx idx, faceidx smooth, int smoothlevel)
2544 root 1.177 CODE:
2545 root 1.184 faceinfo *f = face_info (idx); assert (f);
2546     f->smooth = smooth;
2547     f->smoothlevel = smoothlevel;
2548 root 1.177
2549     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2550 root 1.176 CODE:
2551 root 1.182 {
2552 root 1.176 facedata *d = face_data (idx, faceset);
2553 root 1.177 assert (d);
2554 root 1.181 sv_to (data, d->data);
2555     STRLEN clen;
2556     char *cdata = SvPVbyte (chksum, clen);
2557 root 1.182 clen = min (CHKSUM_SIZE, clen);
2558    
2559     if (memcmp (d->chksum, cdata, clen))
2560     {
2561     memcpy (d->chksum, cdata, clen);
2562    
2563     // invalidate existing client face info
2564     for_all_clients (ns)
2565     if (ns->faceset == faceset)
2566     {
2567     ns->faces_sent [idx] = false;
2568     ns->force_newmap = true;
2569     }
2570     }
2571     }
2572 root 1.176
2573 root 1.177 void invalidate (faceidx idx)
2574     CODE:
2575     for_all_clients (ns)
2576 root 1.182 {
2577     ns->faces_sent [idx] = false;
2578     ns->force_newmap = true;
2579     }
2580 root 1.177
2581     void invalidate_all ()
2582     CODE:
2583     for_all_clients (ns)
2584 root 1.182 {
2585     ns->faces_sent.reset ();
2586     ns->force_newmap = true;
2587     }
2588 root 1.177
2589 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2590    
2591     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2592    
2593     animidx anim_find (utf8_string name)
2594     CODE:
2595     RETVAL = animation::find (name).number;
2596     OUTPUT: RETVAL
2597    
2598     animidx set (utf8_string name, SV *frames, int facings = 1)
2599     CODE:
2600     {
2601     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2602     croak ("frames must be an arrayref");
2603    
2604     AV *av = (AV *)SvRV (frames);
2605    
2606     animation *anim = &animation::find (name);
2607     if (anim->number)
2608     {
2609     anim->resize (av_len (av) + 1);
2610     anim->facings = facings;
2611     }
2612     else
2613     anim = &animation::create (name, av_len (av) + 1, facings);
2614    
2615     for (int i = 0; i < anim->num_animations; ++i)
2616     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2617     }
2618     OUTPUT: RETVAL
2619    
2620     void invalidate_all ()
2621     CODE:
2622     for_all_clients (ns)
2623     ns->anims_sent.reset ();
2624