ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.146
Committed: Fri Jan 19 22:24:10 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.145: +5 -5 lines
Log Message:
fix random number generator seeding

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