ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.161
Committed: Thu Feb 1 19:15:39 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.160: +11 -10 lines
Log Message:
- improve error messages from object_thawer to incldue line numbers
- provide geenric parse error handler
- finish basic design of generic object loader
- implement generic regions loader
- use it to load regions:
  loader_region loader;
  if (!loader.load (filename))
    error;
- regions should now be the very first filetype that could be reloaded at runtime

File Contents

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