ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.191
Committed: Tue Apr 17 18:40:32 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.190: +0 -3 lines
Log Message:
- load_resource_file cna now load archetypes, regions and treasures
  freely intermingled. archetypes and treasures makes a lot of actual
  sense, too.

(this has not been tested, but unlikely not to work :)

File Contents

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