ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.165
Committed: Tue Feb 13 16:23:32 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.164: +9 -0 lines
Log Message:
- make server more fragile w.r.t. watchdog on freeze
- try to make a perl backtrace on crash, too.

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