ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.204
Committed: Mon Apr 30 04:25:30 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.203: +0 -1 lines
Log Message:
This is the first rough cut of the skill use system (use the STABLE tag).

Details will likely change, and combat skills do not work very well, but
it works quite well.

Players no longer have a shoottype or range slots, instead, each player
has these members:

   combat_skill/combat_ob  the currently selected skill (and weapon)
                           for direct attacks.
   ranged_skill/ranged_ob  the currently selected ranged skill (and
                           bow/spell/item)
   golem                   the currently-controlled golem, if any.

File Contents

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