ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.209
Committed: Thu May 17 14:14:55 2007 UTC (17 years ago) by root
Branch: MAIN
Changes since 1.208: +3 -5 lines
Log Message:
remove superfluous/broken settings and related code

- COZY_SERVER:
  enabled most msall adjustments, changed digestion formula to the original one,
  party member treament w.r.t. pets enforced.
- PROHIBIT_PLAYERKILL: default
- real_wiz: removed and enforced
- create_home_portals: removed and enforced
- casting_time: removed and forced to be off (was crashing anyways)
- was_wiz flag removed and treated as off usually unless it was used
  in place of flag_wiz.
- do not save or restore wiz, wizcast and wizpass flags.

File Contents

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