ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.162
Committed: Thu Feb 1 19:40:42 2007 UTC (17 years, 4 months ago) by root
Branch: MAIN
Changes since 1.161: +15 -0 lines
Log Message:
load regions from perl, reload on, well, reload

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