ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.289
Committed: Thu May 8 20:03:50 2008 UTC (16 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-2_54
Changes since 1.288: +18 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2 root 1.264 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.216 *
4 root 1.272 * Copyright (©) 2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.216 * Copyright (©) 2001-2005,2007 by Chachkoff Yann
6     * Copyright (©) 2006,2007 by Marc Lehmann <cf@schmorp.de>
7     *
8 root 1.264 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.226 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 root 1.216 *
13 root 1.226 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 root 1.216 *
18 root 1.226 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.216 *
21 root 1.264 * The authors can be reached via e-mail to <support@deliantra.net>
22 root 1.106 */
23 root 1.1
24 root 1.198 #include "autoconf.h"
25    
26 root 1.1 #define PLUGIN_NAME "perl"
27 root 1.13 #define PLUGIN_VERSION "cfperl 0.5"
28 root 1.1
29 root 1.198 #if HAVE_EXECINFO_H
30     # include <execinfo.h>
31     #endif
32    
33 root 1.6 #include <cstdarg>
34 root 1.1
35 root 1.257 #include "global.h"
36 root 1.162 #include "loader.h"
37 root 1.257 #include "../random_maps/random_map.h"
38 root 1.272 #include "evthread.h"
39     #include "sproto.h"
40 root 1.1
41 root 1.125 #include <unistd.h>
42     #if _POSIX_MEMLOCK
43     # include <sys/mman.h>
44     #endif
45    
46 root 1.259 #if HAVE_MALLOC_H
47     # include <malloc.h>
48     #endif
49    
50 root 1.279 #if !__GLIBC__
51     # define malloc_trim(pad) -1
52     #endif
53    
54 root 1.32 #include <EXTERN.h>
55     #include <perl.h>
56     #include <XSUB.h>
57    
58 root 1.107 #include "CoroAPI.h"
59 root 1.1 #include "perlxsi.c"
60    
61     extern sint64 *levels; // the experience table
62    
63 root 1.247 typedef object_thawer &object_thawer_ref;
64     typedef object_freezer &object_freezer_ref;
65 root 1.183
66 root 1.194 typedef std::string std__string;
67    
68 root 1.1 static PerlInterpreter *perl;
69    
70 root 1.220 tstamp NOW, runtime;
71 root 1.116
72 root 1.272 static int tick_inhibit;
73     static int tick_pending;
74    
75 root 1.109 global gbl_ev;
76     static AV *cb_global, *cb_attachable, *cb_object, *cb_player, *cb_client, *cb_type, *cb_map;
77 root 1.272 static SV *sv_runtime, *sv_tick_start, *sv_next_tick, *sv_now;
78 root 1.109
79 root 1.210 bitset<NUM_EVENT_TYPES> ev_want_event;
80     bitset<NUM_TYPES> ev_want_type;
81    
82 root 1.109 static HV
83     *stash_cf,
84     *stash_cf_object_wrap,
85     *stash_cf_object_player_wrap,
86     *stash_cf_player_wrap,
87     *stash_cf_map_wrap,
88     *stash_cf_client_wrap,
89     *stash_cf_arch_wrap,
90     *stash_cf_party_wrap,
91     *stash_cf_region_wrap,
92     *stash_cf_living_wrap;
93    
94 root 1.246 static inline SV *
95     newSVpv_utf8 (const char *s)
96     {
97 root 1.252 if (!s)
98     return newSV (0);
99    
100 root 1.246 SV *sv = newSVpv (s, 0);
101     SvUTF8_on (sv);
102     return sv;
103     }
104    
105     static inline SV *
106     newSVpvn_utf8 (const char *s, STRLEN l)
107     {
108 root 1.252 if (!s)
109     return newSV (0);
110    
111 root 1.246 SV *sv = newSVpvn (s, l);
112     SvUTF8_on (sv);
113     return sv;
114     }
115    
116 root 1.109 // helper cast function, returns super class * or 0
117     template<class super>
118     static super *
119     is_a (attachable *at)
120     {
121     //return dynamic_cast<super *>(at); // slower, safer
122     if (typeid (*at) == typeid (super))
123     return static_cast<super *>(at);
124     else
125     return 0;
126     }
127    
128     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
129    
130     unordered_vector<attachable *> attachable::mortals;
131    
132 root 1.129 attachable::~attachable ()
133 root 1.109 {
134 root 1.133 assert (!self);
135 root 1.153 assert (!cb);
136 root 1.109 }
137    
138 root 1.130 int
139     attachable::refcnt_cnt () const
140     {
141 root 1.152 return refcnt + (self ? SvREFCNT (self) - 1 : 0);
142 root 1.130 }
143    
144     void
145 root 1.155 attachable::sever_self ()
146 root 1.109 {
147 root 1.164 if (HV *self = this->self)
148 root 1.129 {
149 root 1.155 // keep a refcount because sv_unmagic might call attachable_free,
150     // which might clear self, causing sv_unmagic to crash on a now
151     // invalid object.
152 root 1.154 SvREFCNT_inc (self);
153 root 1.155 hv_clear (self);
154     sv_unmagic ((SV *)self, PERL_MAGIC_ext);
155 root 1.154 SvREFCNT_dec (self);
156 root 1.155
157     // self *must* be null now because thats sv_unmagic's job.
158 root 1.164 assert (!this->self);
159 root 1.129 }
160 root 1.109 }
161    
162 root 1.155 void
163     attachable::optimise ()
164     {
165     if (self
166     && SvREFCNT (self) == 1
167     && !HvTOTALKEYS (self))
168     sever_self ();
169     }
170    
171 root 1.109 // check wether the object really is dead
172     void
173     attachable::do_check ()
174     {
175 root 1.152 if (refcnt_cnt () > 0)
176 root 1.109 return;
177    
178 root 1.133 destroy ();
179 root 1.109 }
180    
181     void
182     attachable::do_destroy ()
183     {
184 root 1.214 INVOKE_ATTACHABLE (DESTROY, this);
185 root 1.109
186 root 1.153 if (cb)
187     {
188     SvREFCNT_dec (cb);
189     cb = 0;
190     }
191    
192 root 1.109 mortals.push_back (this);
193     }
194    
195     void
196     attachable::destroy ()
197     {
198     if (destroyed ())
199     return;
200    
201     flags |= F_DESTROYED;
202     do_destroy ();
203 root 1.198 sever_self ();
204 root 1.109 }
205    
206 root 1.130 void
207     attachable::check_mortals ()
208 root 1.109 {
209 root 1.150 static int i = 0;
210    
211     for (;;)
212 root 1.109 {
213 root 1.150 if (i >= mortals.size ())
214     {
215     i = 0;
216    
217 root 1.221 if (mortals.size () >= 512)
218     {
219     static int last_mortalcount;
220     if (mortals.size () != last_mortalcount)
221     {
222     last_mortalcount = mortals.size ();
223     LOG (llevInfo, "%d mortals.\n", (int)mortals.size ());
224    
225     if (0)
226     {
227     for (int j = 0; j < mortals.size (); ++j)//D
228     fprintf (stderr, "%d:%s %p ", j, &((object *)mortals[j])->name, mortals[j]);//D
229     fprintf (stderr, "\n");//D
230     }
231     }
232     }
233 root 1.150
234     break;
235     }
236    
237 root 1.109 attachable *obj = mortals [i];
238    
239 root 1.197 #if 0
240     if (obj->self)//D make this an assert later
241     {
242     LOG (llevError, "check_mortals: object '%s' still has self\n", typeid (obj).name ());
243     obj->sever_self ();
244     }
245     #endif
246 root 1.109
247 root 1.198 if (obj->refcnt)
248 root 1.109 {
249 root 1.150 ++i; // further delay freeing
250 root 1.109
251 root 1.150 if (!(i & 0x3ff))
252     break;
253     }
254 root 1.109 else
255     {
256 root 1.112 mortals.erase (i);
257 root 1.197 obj->sever_self ();
258 root 1.109 delete obj;
259     }
260     }
261     }
262    
263 root 1.228 void
264 root 1.246 attachable::set_key (const char *key, const char *value, bool is_utf8)
265 root 1.228 {
266     if (!self)
267     self = newHV ();
268    
269     if (value)
270 root 1.246 hv_store (self, key, strlen (key), is_utf8 ? newSVpv_utf8 (value) : newSVpv (value, 0), 0);
271 root 1.228 else
272     hv_delete (self, key, strlen (key), G_DISCARD);
273     }
274    
275 root 1.109 attachable &
276     attachable::operator =(const attachable &src)
277     {
278     //if (self || cb)
279     //INVOKE_OBJECT (CLONE, this, ARG_OBJECT (dst));
280    
281     attach = src.attach;
282     return *this;
283     }
284 root 1.8
285 root 1.221 template<typename T>
286     static bool
287     find_backref (void *ptr, T *obj)
288     {
289     char *s = (char *)obj;
290     while (s < (char *)obj + sizeof (T))
291     {
292     if (ptr == *(void **)s)
293     return true;
294    
295     s += sizeof (void *); // assume natural alignment
296     }
297    
298     return false;
299     }
300    
301     // for debugging, find "live" objects containing this ptr
302     void
303     find_backref (void *ptr)
304     {
305     for_all_objects (op)
306     if (find_backref (ptr, op))
307     fprintf (stderr, "O %p %d:'%s'\n", op, op->count, &op->name);
308    
309     for_all_players (pl)
310     if (find_backref (ptr, pl))
311     fprintf (stderr, "P %p\n", pl);
312    
313     for_all_clients (ns)
314     if (find_backref (ptr, ns))
315     fprintf (stderr, "C %p\n", ns);
316    
317     }
318    
319 root 1.1 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
320    
321     static SV *
322 root 1.109 newSVptr (void *ptr, HV *stash, HV *hv = newHV ())
323 root 1.1 {
324     SV *sv;
325    
326     if (!ptr)
327 root 1.252 return newSV (0);
328 root 1.1
329 root 1.109 sv_magicext ((SV *)hv, 0, PERL_MAGIC_ext, 0, (char *)ptr, 0);
330     return sv_bless (newRV_noinc ((SV *)hv), stash);
331     }
332    
333     static int
334     attachable_free (pTHX_ SV *sv, MAGIC *mg)
335     {
336     attachable *at = (attachable *)mg->mg_ptr;
337 root 1.153
338     //TODO: check if transaction behaviour is really required here
339     if (SV *self = (SV *)at->self)
340     {
341     at->self = 0;
342     SvREFCNT_dec (self);
343     }
344    
345 root 1.111 // next line makes sense, but most objects still have refcnt 0 by default
346     //at->refcnt_chk ();
347 root 1.109 return 0;
348 root 1.1 }
349    
350 root 1.116 MGVTBL attachable::vtbl = {0, 0, 0, 0, attachable_free};
351 root 1.109
352 root 1.116 static SV *
353 root 1.109 newSVattachable (attachable *obj, HV *stash)
354 root 1.11 {
355     if (!obj)
356 root 1.252 return newSV (0);
357 root 1.11
358     if (!obj->self)
359 root 1.228 obj->self = newHV ();
360    
361     if (!SvOBJECT (obj->self))
362 root 1.109 {
363 root 1.116 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
364 root 1.11
365 root 1.129 // now bless the object _once_
366 root 1.228 //TODO: create a class registry with c++ type<=>perl name<=>stash and use it here and elsewhere
367 root 1.129 return sv_bless (newRV_inc ((SV *)obj->self), stash);
368 root 1.109 }
369 root 1.129 else
370 root 1.140 {
371     SV *sv = newRV_inc ((SV *)obj->self);
372    
373     if (Gv_AMG (stash)) // handle overload correctly, as the perl core does not
374     SvAMAGIC_on (sv);
375    
376     return sv;
377     }
378 root 1.11 }
379    
380 root 1.1 static void
381     clearSVptr (SV *sv)
382     {
383     if (SvROK (sv))
384     sv = SvRV (sv);
385    
386     hv_clear ((HV *)sv);
387     sv_unmagic (sv, PERL_MAGIC_ext);
388     }
389    
390     static long
391     SvPTR (SV *sv, const char *klass)
392     {
393     if (!sv_derived_from (sv, klass))
394     croak ("object of type %s expected", klass);
395    
396     MAGIC *mg = mg_find (SvRV (sv), PERL_MAGIC_ext);
397    
398     if (!mg)
399     croak ("perl code used %s object, but C object is already destroyed, caught", klass);
400    
401     return (long)mg->mg_ptr;
402     }
403    
404     static long
405     SvPTR_ornull (SV *sv, const char *klass)
406     {
407     if (SvOK (sv))
408     return SvPTR (sv, klass);
409     else
410     return 0;
411     }
412    
413 root 1.252 inline SV *to_sv (const shstr & v) { return newSVpvn_utf8 ((const char *)v, v.length ()); }
414     inline SV *to_sv (const char * v) { return v ? newSVpv (v, 0) : newSV (0); }
415 root 1.45 inline SV *to_sv (bool v) { return newSViv (v); }
416     inline SV *to_sv ( signed char v) { return newSViv (v); }
417     inline SV *to_sv (unsigned char v) { return newSViv (v); }
418     inline SV *to_sv ( signed short v) { return newSViv (v); }
419     inline SV *to_sv (unsigned short v) { return newSVuv (v); }
420     inline SV *to_sv ( signed int v) { return newSViv (v); }
421     inline SV *to_sv (unsigned int v) { return newSVuv (v); }
422     inline SV *to_sv ( signed long v) { return newSViv (v); }
423     inline SV *to_sv (unsigned long v) { return newSVuv (v); }
424 root 1.48 inline SV *to_sv ( signed long long v) { return newSVval64 (v); }
425     inline SV *to_sv (unsigned long long v) { return newSVval64 (v); }
426 root 1.45 inline SV *to_sv (float v) { return newSVnv (v); }
427     inline SV *to_sv (double v) { return newSVnv (v); }
428 root 1.109 inline SV *to_sv (client * v) { return newSVattachable (v, stash_cf_client_wrap); }
429     inline SV *to_sv (player * v) { return newSVattachable (v, stash_cf_player_wrap); }
430     inline SV *to_sv (object * v) { return newSVattachable (v, v && v->type == PLAYER ? stash_cf_object_player_wrap : stash_cf_object_wrap); }
431     inline SV *to_sv (maptile * v) { return newSVattachable (v, stash_cf_map_wrap); }
432     inline SV *to_sv (archetype * v) { return newSVattachable (v, stash_cf_arch_wrap); }
433 root 1.228 inline SV *to_sv (region * v) { return newSVattachable (v, stash_cf_region_wrap); }
434 root 1.109 inline SV *to_sv (partylist * v) { return newSVptr (v, stash_cf_party_wrap); }
435     inline SV *to_sv (living * v) { return newSVptr (v, stash_cf_living_wrap); }
436 root 1.45
437     inline SV *to_sv (object & v) { return to_sv (&v); }
438     inline SV *to_sv (living & v) { return to_sv (&v); }
439    
440 root 1.194 inline SV *to_sv (const std::string & v) { return newSVpvn (v.data (), v.size ()); }
441     inline SV *to_sv (const treasurelist *v) { return to_sv (v->name); }
442 root 1.45
443 root 1.275 inline SV *to_sv (UUID v) { return newSVpv (v.c_str (), 0); }
444 elmex 1.68
445 root 1.247 inline void sv_to (SV *sv, shstr &v) { v = SvOK (sv) ? SvPVutf8_nolen (sv) : 0; }
446     inline void sv_to (SV *sv, char * &v) { free (v); v = SvOK (sv) ? strdup (SvPV_nolen (sv)) : 0; }
447     inline void sv_to (SV *sv, bool &v) { v = SvIV (sv); }
448     inline void sv_to (SV *sv, signed char &v) { v = SvIV (sv); }
449     inline void sv_to (SV *sv, unsigned char &v) { v = SvIV (sv); }
450     inline void sv_to (SV *sv, signed short &v) { v = SvIV (sv); }
451     inline void sv_to (SV *sv, unsigned short &v) { v = SvIV (sv); }
452     inline void sv_to (SV *sv, signed int &v) { v = SvIV (sv); }
453     inline void sv_to (SV *sv, unsigned int &v) { v = SvUV (sv); }
454     inline void sv_to (SV *sv, signed long &v) { v = SvIV (sv); }
455     inline void sv_to (SV *sv, unsigned long &v) { v = SvUV (sv); }
456 root 1.53 inline void sv_to (SV *sv, signed long long &v) { v = ( signed long long)SvVAL64 (sv); }
457     inline void sv_to (SV *sv, unsigned long long &v) { v = (unsigned long long)SvVAL64 (sv); }
458 root 1.247 inline void sv_to (SV *sv, float &v) { v = SvNV (sv); }
459     inline void sv_to (SV *sv, double &v) { v = SvNV (sv); }
460     inline void sv_to (SV *sv, client * &v) { v = (client *)(attachable *)SvPTR_ornull (sv, "cf::client"); }
461     inline void sv_to (SV *sv, player * &v) { v = (player *)(attachable *)SvPTR_ornull (sv, "cf::player"); }
462     inline void sv_to (SV *sv, object * &v) { v = (object *)(attachable *)SvPTR_ornull (sv, "cf::object"); }
463     inline void sv_to (SV *sv, archetype * &v) { v = (archetype *)(attachable *)SvPTR_ornull (sv, "cf::arch"); }
464     inline void sv_to (SV *sv, maptile * &v) { v = (maptile *)(attachable *)SvPTR_ornull (sv, "cf::map"); }
465     inline void sv_to (SV *sv, region * &v) { v = (region *)(attachable *)SvPTR_ornull (sv, "cf::region"); }
466     inline void sv_to (SV *sv, attachable * &v) { v = (attachable *)SvPTR_ornull (sv, "cf::attachable"); }
467     inline void sv_to (SV *sv, partylist * &v) { v = (partylist *)SvPTR_ornull (sv, "cf::party"); }
468     inline void sv_to (SV *sv, living * &v) { v = (living *)SvPTR_ornull (sv, "cf::living"); }
469     inline void sv_to (SV *sv, object_freezer * &v) { v = (object_freezer *)SvPTR_ornull (sv, "cf::object::freezer"); }
470     inline void sv_to (SV *sv, object_thawer * &v) { v = (object_thawer *)SvPTR_ornull (sv, "cf::object::thawer" ); }
471 root 1.45
472 root 1.247 //inline void sv_to (SV *sv, faceinfo * &v) { v = &faces [face_find (SvPV_nolen (sv), 0)]; }
473     inline void sv_to (SV *sv, treasurelist * &v) { v = treasurelist::find (SvPV_nolen (sv)); }
474 root 1.45
475 root 1.52 template<class T>
476 root 1.247 inline void sv_to (SV *sv, refptr<T> &v) { T *tmp; sv_to (sv, tmp); v = tmp; }
477 root 1.52
478 root 1.45 template<int N>
479 root 1.55 inline void sv_to (SV *sv, char (&v)[N]) { assign (v, SvPV_nolen (sv)); }
480 root 1.45
481 root 1.247 inline void sv_to (SV *sv, bowtype_t &v) { v = (bowtype_t) SvIV (sv); }
482     inline void sv_to (SV *sv, petmode_t &v) { v = (petmode_t) SvIV (sv); }
483     inline void sv_to (SV *sv, usekeytype &v) { v = (usekeytype) SvIV (sv); }
484     inline void sv_to (SV *sv, unapplymode &v) { v = (unapplymode) SvIV (sv); }
485 root 1.106
486 root 1.247 inline void sv_to (SV *sv, std::string &v)
487 root 1.176 {
488     STRLEN len;
489     char *data = SvPVbyte (sv, len);
490     v.assign (data, len);
491     }
492    
493 root 1.247 inline void sv_to (SV *sv, UUID &v)
494 root 1.69 {
495 root 1.275 if (!v.parse (SvPV_nolen (sv)))
496 root 1.69 croak ("unparsable uuid: %s", SvPV_nolen (sv));
497 elmex 1.68 }
498    
499 root 1.109 inline void sv_to (SV *sv, object::flags_t::reference v) { v = SvTRUE (sv); }
500 root 1.106
501 root 1.1 static SV *
502 root 1.6 newSVdt_va (va_list &ap, data_type type)
503 root 1.1 {
504     SV *sv;
505    
506     switch (type)
507     {
508 root 1.10 case DT_INT:
509     sv = newSViv (va_arg (ap, int));
510     break;
511    
512     case DT_INT64:
513     sv = newSVval64 ((val64)va_arg (ap, sint64));
514     break;
515    
516 root 1.6 case DT_DOUBLE:
517 root 1.10 sv = newSVnv (va_arg (ap, double));
518 root 1.1 break;
519    
520 root 1.6 case DT_STRING:
521     {
522 root 1.10 char *str = (char *)va_arg (ap, const char *);
523 root 1.252 sv = str ? newSVpv (str, 0) : newSV (0);
524 root 1.6 }
525 root 1.1 break;
526    
527 root 1.6 case DT_DATA:
528 root 1.1 {
529 root 1.10 char *str = (char *)va_arg (ap, const void *);
530 root 1.6 int len = va_arg (ap, int);
531 root 1.252 sv = str ? newSVpv (str, len) : newSV (0);
532 root 1.1 }
533     break;
534    
535 root 1.6 case DT_OBJECT:
536 root 1.45 sv = to_sv (va_arg (ap, object *));
537 root 1.1 break;
538    
539 root 1.6 case DT_MAP:
540 root 1.11 // va_arg (object *) when void * is passed is an XSI extension
541 root 1.61 sv = to_sv (va_arg (ap, maptile *));
542 root 1.1 break;
543    
544 root 1.88 case DT_CLIENT:
545 root 1.84 sv = to_sv (va_arg (ap, client *));
546 root 1.79 break;
547    
548 root 1.6 case DT_PLAYER:
549 root 1.45 sv = to_sv (va_arg (ap, player *));
550 root 1.1 break;
551    
552 root 1.6 case DT_ARCH:
553 root 1.45 sv = to_sv (va_arg (ap, archetype *));
554 root 1.1 break;
555    
556 root 1.6 case DT_PARTY:
557 root 1.45 sv = to_sv (va_arg (ap, partylist *));
558 root 1.1 break;
559    
560 root 1.6 case DT_REGION:
561 root 1.45 sv = to_sv (va_arg (ap, region *));
562 root 1.1 break;
563    
564     default:
565 root 1.6 assert (("unhandled type in newSVdt_va", 0));
566     }
567    
568     return sv;
569     }
570    
571     static SV *
572     newSVdt (data_type type, ...)
573     {
574     va_list ap;
575    
576     va_start (ap, type);
577     SV *sv = newSVdt_va (ap, type);
578     va_end (ap);
579    
580     return sv;
581     }
582    
583 root 1.11 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
584    
585 root 1.12 SV *
586 root 1.109 registry (attachable *ext)
587 root 1.12 {
588 root 1.13 if (!ext->cb)
589     ext->cb = newAV ();
590 root 1.12
591 root 1.13 return newRV_inc ((SV *)ext->cb);
592 root 1.12 }
593    
594 root 1.13 /////////////////////////////////////////////////////////////////////////////
595    
596 root 1.7 void
597     cfperl_init ()
598     {
599 root 1.270 extern char **environ;
600    
601     PERL_SYS_INIT3 (&settings.argc, &settings.argv, &environ);
602 root 1.32 perl = perl_alloc ();
603     perl_construct (perl);
604    
605     PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
606    
607 root 1.179 const char *argv[] = {
608 root 1.198 settings.argv [0],
609 root 1.7 "-e"
610 root 1.265 "use EV; use Coro;" // required for bootstrap
611     "cf->bootstrap;" // required for datadir :*>
612 root 1.32 "unshift @INC, cf::datadir ();"
613 root 1.41 "require cf;"
614 root 1.7 };
615    
616 root 1.270 if (perl_parse (perl, xs_init, 2, (char **)argv, environ)
617 root 1.179 || perl_run (perl))
618 root 1.7 {
619     printf ("unable to initialize perl-interpreter, aborting.\n");
620     exit (EXIT_FAILURE);
621     }
622 root 1.162
623     {
624     dSP;
625    
626     PUSHMARK (SP);
627     PUTBACK;
628     call_pv ("cf::init", G_DISCARD | G_VOID);
629     }
630 root 1.7 }
631    
632 root 1.5 void cfperl_main ()
633 root 1.2 {
634     dSP;
635    
636     PUSHMARK (SP);
637     PUTBACK;
638 root 1.7 call_pv ("cf::main", G_DISCARD | G_VOID);
639     }
640    
641 root 1.109 void
642     attachable::instantiate ()
643     {
644     if (attach)
645     {
646 root 1.214 INVOKE_ATTACHABLE (INSTANTIATE, this, ARG_STRING (attach));
647 root 1.109 attach = 0;
648     }
649     }
650    
651     void
652     attachable::reattach ()
653     {
654     optimise ();
655     //TODO: check for _attachment's, very important for restarts
656 root 1.214 INVOKE_ATTACHABLE (REATTACH, this);
657 root 1.109 }
658    
659 root 1.8 static event_klass klass_of[NUM_EVENT_TYPES] = {
660     # define def(type,name) KLASS_ ## type,
661     # include "eventinc.h"
662     # undef def
663     };
664    
665 root 1.18 #define KLASS_OF(event) (((unsigned int)event) < NUM_EVENT_TYPES ? klass_of [event] : KLASS_NONE)
666    
667 root 1.8 static void
668     gather_callbacks (AV *&callbacks, AV *registry, event_type event)
669     {
670     // event must be in array
671     if (event >= 0 && event <= AvFILLp (registry))
672     {
673     SV *cbs_ = AvARRAY (registry)[event];
674    
675     // element must be list of callback entries
676     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
677     {
678     AV *cbs = (AV *)SvRV (cbs_);
679    
680     // no callback entries, no callbacks to call
681     if (AvFILLp (cbs) >= 0)
682     {
683     if (!callbacks)
684     {
685     callbacks = newAV ();
686     av_extend (callbacks, 16);
687     }
688    
689     // never use SvREFCNT_inc to copy values, but its ok here :)
690     for (int i = 0; i <= AvFILLp (cbs); ++i)
691     av_push (callbacks, SvREFCNT_inc (AvARRAY (cbs)[i]));
692     }
693     }
694     }
695     }
696    
697 root 1.109 void
698     attachable::gather_callbacks (AV *&callbacks, event_type event) const
699 root 1.6 {
700 root 1.109 ::gather_callbacks (callbacks, cb_attachable, event);
701 root 1.6
702 root 1.109 if (cb)
703     ::gather_callbacks (callbacks, cb, event);
704     }
705 root 1.8
706 root 1.109 void
707     global::gather_callbacks (AV *&callbacks, event_type event) const
708     {
709 root 1.210 ::gather_callbacks (callbacks, cb_global, event);
710 root 1.109 }
711 root 1.8
712 root 1.109 void
713     object::gather_callbacks (AV *&callbacks, event_type event) const
714     {
715 root 1.210 if (subtype && type + subtype * NUM_TYPES <= AvFILLp (cb_type))
716 root 1.109 {
717 root 1.210 SV *registry = AvARRAY (cb_type)[type + subtype * NUM_TYPES];
718 root 1.8
719 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
720     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
721     }
722 root 1.8
723 root 1.109 if (type <= AvFILLp (cb_type))
724 root 1.8 {
725 root 1.109 SV *registry = AvARRAY (cb_type)[type];
726 root 1.8
727 root 1.109 if (registry && SvROK (registry) && SvTYPE (SvRV (registry)) == SVt_PVAV)
728     ::gather_callbacks (callbacks, (AV *)SvRV (registry), event);
729     }
730 root 1.8
731 root 1.109 attachable::gather_callbacks (callbacks, event);
732     ::gather_callbacks (callbacks, cb_object, event);
733     }
734 root 1.8
735 root 1.109 void
736     archetype::gather_callbacks (AV *&callbacks, event_type event) const
737     {
738     attachable::gather_callbacks (callbacks, event);
739     //TODO//::gather_callbacks (callbacks, cb_archetype, event);
740     }
741 root 1.14
742 root 1.109 void
743     client::gather_callbacks (AV *&callbacks, event_type event) const
744     {
745     attachable::gather_callbacks (callbacks, event);
746     ::gather_callbacks (callbacks, cb_client, event);
747     }
748 root 1.8
749 root 1.109 void
750     player::gather_callbacks (AV *&callbacks, event_type event) const
751     {
752     attachable::gather_callbacks (callbacks, event);
753     ::gather_callbacks (callbacks, cb_player, event);
754     }
755 root 1.8
756 root 1.109 void
757     maptile::gather_callbacks (AV *&callbacks, event_type event) const
758     {
759     attachable::gather_callbacks (callbacks, event);
760     ::gather_callbacks (callbacks, cb_map, event);
761     }
762 root 1.8
763 root 1.210 void
764     _recalc_want (bitset<NUM_EVENT_TYPES> &set, AV *registry)
765     {
766     for (int event = 0; event <= AvFILLp (registry); ++event)
767     {
768     SV *cbs_ = AvARRAY (registry)[event];
769    
770     // element must be list of callback entries
771     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
772     {
773     AV *cbs = (AV *)SvRV (cbs_);
774    
775     // no callback entries, no callbacks to call
776     if (AvFILLp (cbs) >= 0)
777     set.set (event);
778     }
779     }
780     }
781    
782     // very slow and inefficient way to recalculate the global want bitsets
783     void
784     _recalc_want ()
785     {
786     ev_want_event.reset ();
787    
788     _recalc_want (ev_want_event, cb_global);
789     _recalc_want (ev_want_event, cb_attachable);
790     _recalc_want (ev_want_event, cb_object);
791     _recalc_want (ev_want_event, cb_client);
792     _recalc_want (ev_want_event, cb_player);
793     _recalc_want (ev_want_event, cb_map);
794    
795     ev_want_type.reset ();
796    
797     for (int type = 0; type <= AvFILLp (cb_type); ++type)
798     {
799     SV *cbs_ = AvARRAY (cb_type)[type];
800    
801     // element must be list of callback entries
802     if (cbs_ && SvROK (cbs_) && SvTYPE (SvRV (cbs_)) == SVt_PVAV)
803     {
804     AV *cbs = (AV *)SvRV (cbs_);
805    
806     // no callback entries, no callbacks to call
807     if (AvFILLp (cbs) >= 0)
808     ev_want_type.set (type % NUM_TYPES);
809     }
810     }
811     }
812    
813 root 1.109 bool
814 root 1.214 attachable::invoke (event_type event, ...)
815 root 1.109 {
816     data_type dt;
817 root 1.8
818 root 1.109 // callback call ordering should be:
819     // 1. per-object callback
820     // 2. per-class object
821     // 3. per-type callback
822     // 4. global callbacks
823 root 1.12
824 root 1.109 AV *callbacks = 0;
825     gather_callbacks (callbacks, event);
826 root 1.8
827     // short-circuit processing if no callbacks found/defined
828     if (!callbacks)
829     return 0;
830    
831 root 1.214 va_list ap;
832     va_start (ap, event);
833    
834 root 1.116 CALL_BEGIN (3);
835     CALL_ARG_SV (newSViv (event)); // only used for debugging nowadays
836     CALL_ARG_SV (newRV_noinc ((SV *)callbacks));
837 root 1.8
838 root 1.109 //TODO: unhack
839 root 1.116 if (object *op = is_a<object>(this)) CALL_ARG_SV (newSVdt (DT_OBJECT, op));
840     else if (player *pl = is_a<player>(this)) CALL_ARG_SV (newSVdt (DT_PLAYER, pl));
841     else if (client *ns = is_a<client>(this)) CALL_ARG_SV (newSVdt (DT_CLIENT, ns));
842     else if (maptile *m = is_a<maptile>(this)) CALL_ARG_SV (newSVdt (DT_MAP, m));
843 root 1.109 else if (global *gl = is_a<global>(this)) /*nop*/;
844     else
845     abort (); //TODO
846 root 1.7
847 root 1.6 for (;;)
848     {
849 root 1.8 dt = (data_type) va_arg (ap, int);
850 root 1.6
851     if (dt == DT_END)
852     break;
853 root 1.109 else if (dt == DT_AV)
854 root 1.12 {
855     AV *av = va_arg (ap, AV *);
856    
857     for (int i = 0; i <= av_len (av); ++i)
858     XPUSHs (*av_fetch (av, i, 1));
859     }
860     else
861     XPUSHs (sv_2mortal (newSVdt_va (ap, dt)));
862 root 1.6 }
863    
864     va_end (ap);
865    
866 root 1.116 CALL_CALL ("cf::do_invoke", G_SCALAR);
867 root 1.6 count = count > 0 ? POPi : 0;
868    
869 root 1.116 CALL_END;
870 root 1.6
871     return count;
872 root 1.2 }
873    
874 root 1.12 SV *
875     cfperl_result (int idx)
876     {
877 elmex 1.233 AV *av = get_av ("cf::INVOKE_RESULTS", 0);
878 root 1.12 if (!av)
879     return &PL_sv_undef;
880    
881     SV **sv = av_fetch (av, idx, 0);
882     if (!sv)
883     return &PL_sv_undef;
884    
885     return *sv;
886     }
887    
888     int
889     cfperl_result_INT (int idx)
890     {
891     return SvIV (cfperl_result (idx));
892     }
893    
894 root 1.74 double
895 root 1.73 cfperl_result_DOUBLE (int idx)
896     {
897     return SvNV (cfperl_result (idx));
898     }
899    
900 root 1.80 /////////////////////////////////////////////////////////////////////////////
901 root 1.247 // various c++ => perl glue functions
902 root 1.80
903 root 1.272 void cfperl_tick ()
904     {
905     tick_pending = 1;
906    
907     if (tick_inhibit)
908     return;
909    
910     tick_pending = 0;
911    
912     dSP;
913    
914     PUSHMARK (SP);
915     PUTBACK;
916     call_pv ("cf::tick", G_DISCARD | G_VOID);
917    
918     SvNV_set (sv_next_tick, get_next_tick ()); SvNOK_only (sv_next_tick);
919     }
920    
921 root 1.116 void
922 root 1.134 cfperl_emergency_save ()
923 root 1.116 {
924     CALL_BEGIN (0);
925 root 1.134 CALL_CALL ("cf::emergency_save", G_VOID);
926 root 1.116 CALL_END;
927     }
928    
929 root 1.165 void
930     cfperl_cleanup (int make_core)
931     {
932     CALL_BEGIN (1);
933     CALL_ARG (make_core);
934     CALL_CALL ("cf::post_cleanup", G_VOID);
935     CALL_END;
936     }
937    
938 root 1.213 void
939     cfperl_make_book (object *book, int level)
940     {
941     CALL_BEGIN (2);
942     CALL_ARG (book);
943     CALL_ARG (level);
944     CALL_CALL ("ext::books::make_book", G_VOID);
945     CALL_END;
946     }
947    
948 root 1.222 void
949 root 1.289 cfperl_expand_cfpod (player *pl, std::string &msg)
950     {
951     CALL_BEGIN (2);
952     CALL_ARG (pl);
953     CALL_ARG_SV (newSVpvn_utf8 (msg.data (), msg.size ()));
954     CALL_CALL ("cf::player::expand_cfpod", G_SCALAR);
955    
956     if (count)
957     {
958     STRLEN len;
959     char *data = SvPVutf8 (TOPs, len);
960     msg.assign (data, len);
961     }
962    
963     CALL_END;
964     }
965    
966     void
967 root 1.222 cfperl_send_msg (client *ns, int color, const char *type, const char *msg)
968     {
969     CALL_BEGIN (4);
970     CALL_ARG (ns);
971     CALL_ARG (type);
972 root 1.224 CALL_ARG_SV (newSVpv_utf8 (msg));
973 root 1.235 CALL_ARG (color);
974 root 1.222 CALL_CALL ("cf::client::send_msg", G_VOID);
975     CALL_END;
976     }
977    
978 root 1.234 int
979     cfperl_can_merge (object *ob1, object *ob2)
980     {
981     int can;
982    
983     CALL_BEGIN (2);
984     CALL_ARG (ob1);
985     CALL_ARG (ob2);
986     CALL_CALL ("cf::_can_merge", G_SCALAR);
987     can = count && SvTRUE (TOPs);
988     CALL_END;
989    
990     return can;
991     }
992    
993 root 1.244 player *
994     player::find (const char *name)
995     {
996     CALL_BEGIN (1);
997     CALL_ARG (name);
998     CALL_CALL ("cf::player::find", G_SCALAR);
999    
1000 root 1.286 player *retval = 0;
1001     if (count) sv_to (POPs, retval);
1002 root 1.244
1003 root 1.286 CALL_END;
1004    
1005     return retval;
1006     }
1007    
1008     maptile *
1009     find_style (const char *dirname, const char *stylename, int difficulty)
1010     {
1011     CALL_BEGIN (3);
1012     CALL_ARG (dirname);
1013     CALL_ARG (stylename);
1014     CALL_ARG (difficulty);
1015     CALL_CALL ("ext::map_random::find_style", G_SCALAR);
1016    
1017     maptile *retval = 0;
1018     if (count) sv_to (POPs, retval);
1019 root 1.244
1020     CALL_END;
1021    
1022     return retval;
1023     }
1024    
1025 root 1.116 maptile *
1026 root 1.126 maptile::find_sync (const char *path, maptile *origin)
1027 root 1.116 {
1028     CALL_BEGIN (2);
1029     CALL_ARG (path);
1030     CALL_ARG (origin);
1031 root 1.126 CALL_CALL ("cf::map::find_sync", G_SCALAR);
1032 root 1.116
1033 root 1.286 maptile *retval = 0;
1034     if (count) sv_to (POPs, retval);
1035 root 1.116
1036     CALL_END;
1037    
1038     return retval;
1039     }
1040    
1041 root 1.135 maptile *
1042 root 1.243 maptile::find_async (const char *path, maptile *origin, bool load)
1043 root 1.135 {
1044 root 1.243 CALL_BEGIN (3);
1045 root 1.135 CALL_ARG (path);
1046     CALL_ARG (origin);
1047 root 1.243 CALL_ARG (load);
1048 root 1.135 CALL_CALL ("cf::map::find_async", G_SCALAR);
1049    
1050 root 1.286 maptile *retval = 0;
1051     if (count) sv_to (POPs, retval);
1052 root 1.135
1053     CALL_END;
1054    
1055     return retval;
1056     }
1057    
1058 root 1.116 void
1059 root 1.126 maptile::do_load_sync ()
1060     {
1061     CALL_BEGIN (1);
1062     CALL_ARG (this);
1063     CALL_CALL ("cf::map::do_load_sync", G_SCALAR);
1064     CALL_END;
1065     }
1066    
1067     void
1068 root 1.116 maptile::change_all_map_light (int change)
1069     {
1070     CALL_BEGIN (1);
1071     CALL_ARG (change);
1072     CALL_CALL ("cf::map::change_all_map_light", G_VOID);
1073     CALL_END;
1074     }
1075    
1076     void
1077     object::enter_exit (object *exit)
1078     {
1079     if (type != PLAYER)
1080     return;
1081    
1082     CALL_BEGIN (2);
1083     CALL_ARG (this);
1084     CALL_ARG (exit);
1085     CALL_CALL ("cf::object::player::enter_exit", G_VOID);
1086     CALL_END;
1087     }
1088    
1089 root 1.287 void
1090     object::player_goto (const char *path, int x, int y)
1091     {
1092     if (type != PLAYER)
1093     return;
1094    
1095     CALL_BEGIN (4);
1096     CALL_ARG (this);
1097     CALL_ARG (path);
1098     CALL_ARG (x);
1099     CALL_ARG (y);
1100     CALL_CALL ("cf::object::player::goto", G_VOID);
1101     CALL_END;
1102     }
1103    
1104 root 1.247 const char *
1105     object::ref () const
1106     {
1107     if (type == PLAYER)
1108     return format ("player/<1.%llx>/%s", (unsigned long long)uuid.seq, &name);
1109     else
1110     return 0;
1111     }
1112    
1113     object *
1114     object::deref (const char *ref)
1115     {
1116 root 1.249 object *retval = 0;
1117 root 1.247
1118 root 1.249 if (ref)
1119     {
1120     CALL_BEGIN (1);
1121     CALL_ARG (ref);
1122     CALL_CALL ("cf::object::deref", G_SCALAR);
1123    
1124     if (count)
1125     sv_to (POPs, retval);
1126 root 1.247
1127 root 1.249 CALL_END;
1128     }
1129 root 1.247
1130     return retval;
1131     }
1132    
1133 root 1.198 void
1134     log_backtrace (const char *msg)
1135     {
1136     #if HAVE_BACKTRACE
1137     void *addr [20];
1138     int size = backtrace (addr, 20);
1139    
1140     CALL_BEGIN (size);
1141     CALL_ARG (msg);
1142     for (int i = 0; i < size; ++i)
1143     CALL_ARG ((IV)addr [i]);
1144     CALL_CALL ("cf::_log_backtrace", G_VOID);
1145     CALL_END;
1146     #endif
1147     }
1148    
1149 root 1.116 /////////////////////////////////////////////////////////////////////////////
1150    
1151 root 1.265 struct EVAPI *evapi::GEVAPI;
1152     struct CoroAPI *coroapi::GCoroAPI;
1153 root 1.80
1154 root 1.189 void coroapi::do_cede_to_tick ()
1155     {
1156 root 1.272 cede_pending = 0;
1157 root 1.189 cede ();
1158     }
1159 root 1.124
1160 root 1.188 void
1161     coroapi::wait_for_tick ()
1162     {
1163     CALL_BEGIN (0);
1164     CALL_CALL ("cf::wait_for_tick", G_DISCARD);
1165     CALL_END;
1166     }
1167    
1168     void
1169     coroapi::wait_for_tick_begin ()
1170     {
1171     CALL_BEGIN (0);
1172     CALL_CALL ("cf::wait_for_tick_begin", G_DISCARD);
1173     CALL_END;
1174     }
1175    
1176 root 1.85 void
1177 root 1.80 iow::poll (int events)
1178     {
1179 root 1.265 if (events != this->events)
1180 root 1.81 {
1181 root 1.265 int active = ev_is_active ((ev_io *)this);
1182     if (active) stop ();
1183     ev_io_set ((ev_io *)this, fd, events);
1184     if (active) start ();
1185 root 1.81 }
1186 root 1.80 }
1187    
1188 root 1.109 void
1189     _connect_to_perl ()
1190     {
1191 root 1.272 stash_cf = gv_stashpv ("cf", 1);
1192 root 1.109
1193     stash_cf_object_wrap = gv_stashpv ("cf::object::wrap", 1);
1194     stash_cf_object_player_wrap = gv_stashpv ("cf::object::player::wrap", 1);
1195     stash_cf_player_wrap = gv_stashpv ("cf::player::wrap", 1);
1196     stash_cf_map_wrap = gv_stashpv ("cf::map::wrap" , 1);
1197     stash_cf_client_wrap = gv_stashpv ("cf::client::wrap", 1);
1198     stash_cf_arch_wrap = gv_stashpv ("cf::arch::wrap" , 1);
1199     stash_cf_party_wrap = gv_stashpv ("cf::party::wrap" , 1);
1200     stash_cf_region_wrap = gv_stashpv ("cf::region::wrap", 1);
1201     stash_cf_living_wrap = gv_stashpv ("cf::living::wrap", 1);
1202    
1203 root 1.272 sv_now = get_sv ("cf::NOW" , 1); SvUPGRADE (sv_now , SVt_NV);
1204     sv_runtime = get_sv ("cf::RUNTIME" , 1); SvUPGRADE (sv_runtime , SVt_NV);
1205     sv_tick_start = get_sv ("cf::TICK_START", 1); SvUPGRADE (sv_tick_start, SVt_NV);
1206     sv_next_tick = get_sv ("cf::NEXT_TICK" , 1); SvUPGRADE (sv_next_tick , SVt_NV);
1207 root 1.116
1208 root 1.109 cb_global = get_av ("cf::CB_GLOBAL", 1);
1209     cb_attachable = get_av ("cf::CB_ATTACHABLE", 1);
1210     cb_object = get_av ("cf::CB_OBJECT", 1);
1211     cb_player = get_av ("cf::CB_PLAYER", 1);
1212     cb_client = get_av ("cf::CB_CLIENT", 1);
1213     cb_type = get_av ("cf::CB_TYPE" , 1);
1214     cb_map = get_av ("cf::CB_MAP" , 1);
1215     }
1216    
1217 root 1.1 MODULE = cf PACKAGE = cf PREFIX = cf_
1218    
1219     BOOT:
1220     {
1221 root 1.265 I_EV_API (PACKAGE); evapi::GEVAPI = GEVAPI;
1222     I_CORO_API (PACKAGE); coroapi::GCoroAPI = GCoroAPI;
1223 root 1.80
1224 root 1.189 _connect_to_perl ();
1225    
1226 root 1.109 newCONSTSUB (stash_cf, "VERSION", newSVpv (VERSION, sizeof (VERSION) - 1));
1227 root 1.63
1228 root 1.220 //{
1229     // require_pv ("Time::HiRes");
1230     //
1231     // SV **svp = hv_fetch (PL_modglobal, "Time::NVtime", 12, 0);
1232     // if (!svp) croak ("Time::HiRes is required");
1233     // if (!SvIOK(*svp)) croak ("Time::NVtime isn’t a function pointer");
1234     // coroapi::time = INT2PTR (double(*)(), SvIV(*svp));
1235     //}
1236 root 1.189
1237 root 1.1 static const struct {
1238     const char *name;
1239     IV iv;
1240     } *civ, const_iv[] = {
1241     # define const_iv(name) { # name, (IV)name },
1242 root 1.189 const_iv (llevError) const_iv (llevInfo) const_iv (llevDebug) const_iv (llevMonster)
1243 root 1.198 const_iv (logBacktrace)
1244 root 1.180
1245 root 1.189 const_iv (Map0Cmd) const_iv (Map1Cmd) const_iv (Map1aCmd)
1246    
1247     const_iv (MAP_CLIENT_X) const_iv (MAP_CLIENT_Y)
1248 root 1.180
1249 root 1.5 const_iv (MAX_TIME)
1250 root 1.258 const_iv (MAXSOCKBUF)
1251 root 1.189
1252 root 1.206 const_iv (NUM_BODY_LOCATIONS)
1253     const_iv (body_range) const_iv (body_shield) const_iv (body_combat)
1254     const_iv (body_arm) const_iv (body_torso) const_iv (body_head)
1255     const_iv (body_neck) const_iv (body_skill) const_iv (body_finger)
1256     const_iv (body_shoulder) const_iv (body_foot) const_iv (body_hand)
1257     const_iv (body_wrist) const_iv (body_waist)
1258 root 1.205
1259 root 1.189 const_iv (PLAYER) const_iv (TRANSPORT) const_iv (ROD) const_iv (TREASURE)
1260     const_iv (POTION) const_iv (FOOD) const_iv (POISON) const_iv (BOOK)
1261     const_iv (CLOCK) const_iv (ARROW) const_iv (BOW) const_iv (WEAPON)
1262     const_iv (ARMOUR) const_iv (PEDESTAL) const_iv (ALTAR) const_iv (LOCKED_DOOR)
1263     const_iv (SPECIAL_KEY) const_iv (MAP) const_iv (DOOR) const_iv (KEY)
1264     const_iv (TIMED_GATE) const_iv (TRIGGER) const_iv (GRIMREAPER) const_iv (MAGIC_EAR)
1265     const_iv (TRIGGER_BUTTON) const_iv (TRIGGER_ALTAR) const_iv (TRIGGER_PEDESTAL) const_iv (SHIELD)
1266     const_iv (HELMET) const_iv (HORN) const_iv (MONEY) const_iv (CLASS)
1267     const_iv (GRAVESTONE) const_iv (AMULET) const_iv (PLAYERMOVER) const_iv (TELEPORTER)
1268     const_iv (CREATOR) const_iv (SKILL) const_iv (EARTHWALL) const_iv (GOLEM)
1269     const_iv (THROWN_OBJ) const_iv (BLINDNESS) const_iv (GOD) const_iv (DETECTOR)
1270     const_iv (TRIGGER_MARKER) const_iv (DEAD_OBJECT) const_iv (DRINK) const_iv (MARKER)
1271     const_iv (HOLY_ALTAR) const_iv (PLAYER_CHANGER) const_iv (BATTLEGROUND) const_iv (PEACEMAKER)
1272     const_iv (GEM) const_iv (FIREWALL) const_iv (ANVIL) const_iv (CHECK_INV)
1273     const_iv (MOOD_FLOOR) const_iv (EXIT) const_iv (ENCOUNTER) const_iv (SHOP_FLOOR)
1274     const_iv (SHOP_MAT) const_iv (RING) const_iv (FLOOR) const_iv (FLESH)
1275     const_iv (INORGANIC) const_iv (SKILL_TOOL) const_iv (LIGHTER) const_iv (BUILDABLE_WALL)
1276     const_iv (MISC_OBJECT) const_iv (LAMP) const_iv (DUPLICATOR) const_iv (SPELLBOOK)
1277     const_iv (CLOAK) const_iv (SPINNER) const_iv (GATE) const_iv (BUTTON)
1278     const_iv (CF_HANDLE) const_iv (HOLE) const_iv (TRAPDOOR) const_iv (SIGN)
1279     const_iv (BOOTS) const_iv (GLOVES) const_iv (SPELL) const_iv (SPELL_EFFECT)
1280     const_iv (CONVERTER) const_iv (BRACERS) const_iv (POISONING) const_iv (SAVEBED)
1281     const_iv (WAND) const_iv (SCROLL) const_iv (DIRECTOR) const_iv (GIRDLE)
1282     const_iv (FORCE) const_iv (POTION_EFFECT) const_iv (EVENT_CONNECTOR) const_iv (CLOSE_CON)
1283     const_iv (CONTAINER) const_iv (ARMOUR_IMPROVER) const_iv (WEAPON_IMPROVER) const_iv (SKILLSCROLL)
1284     const_iv (DEEP_SWAMP) const_iv (IDENTIFY_ALTAR) const_iv (MENU) const_iv (RUNE)
1285     const_iv (TRAP) const_iv (POWER_CRYSTAL) const_iv (CORPSE) const_iv (DISEASE)
1286     const_iv (SYMPTOM) const_iv (BUILDER) const_iv (MATERIAL) const_iv (ITEM_TRANSFORMER)
1287 root 1.1
1288 root 1.210 const_iv (NUM_TYPES) const_iv (NUM_SUBTYPES)
1289 root 1.14
1290 root 1.189 const_iv (ST_BD_BUILD) const_iv (ST_BD_REMOVE)
1291     const_iv (ST_MAT_FLOOR) const_iv (ST_MAT_WALL) const_iv (ST_MAT_ITEM)
1292 root 1.1
1293 root 1.189 const_iv (AT_PHYSICAL) const_iv (AT_MAGIC) const_iv (AT_FIRE) const_iv (AT_ELECTRICITY)
1294     const_iv (AT_COLD) const_iv (AT_CONFUSION) const_iv (AT_ACID) const_iv (AT_DRAIN)
1295     const_iv (AT_WEAPONMAGIC) const_iv (AT_GHOSTHIT) const_iv (AT_POISON) const_iv (AT_SLOW)
1296     const_iv (AT_PARALYZE) const_iv (AT_TURN_UNDEAD) const_iv (AT_FEAR) const_iv (AT_CANCELLATION)
1297     const_iv (AT_DEPLETE) const_iv (AT_DEATH) const_iv (AT_CHAOS) const_iv (AT_COUNTERSPELL)
1298     const_iv (AT_GODPOWER) const_iv (AT_HOLYWORD) const_iv (AT_BLIND) const_iv (AT_INTERNAL)
1299     const_iv (AT_LIFE_STEALING) const_iv (AT_DISEASE)
1300    
1301     const_iv (WEAP_HIT) const_iv (WEAP_SLASH) const_iv (WEAP_PIERCE) const_iv (WEAP_CLEAVE)
1302     const_iv (WEAP_SLICE) const_iv (WEAP_STAB) const_iv (WEAP_WHIP) const_iv (WEAP_CRUSH)
1303 root 1.1 const_iv (WEAP_BLUD)
1304    
1305 root 1.189 const_iv (FLAG_ALIVE) const_iv (FLAG_WIZ) const_iv (FLAG_REMOVED) const_iv (FLAG_FREED)
1306 root 1.209 const_iv (FLAG_APPLIED) const_iv (FLAG_UNPAID) const_iv (FLAG_USE_SHIELD)
1307 root 1.189 const_iv (FLAG_NO_PICK) const_iv (FLAG_ANIMATE) const_iv (FLAG_MONSTER) const_iv (FLAG_FRIENDLY)
1308     const_iv (FLAG_GENERATOR) const_iv (FLAG_IS_THROWN) const_iv (FLAG_AUTO_APPLY) const_iv (FLAG_PLAYER_SOLD)
1309     const_iv (FLAG_SEE_INVISIBLE) const_iv (FLAG_CAN_ROLL) const_iv (FLAG_OVERLAY_FLOOR) const_iv (FLAG_IS_TURNABLE)
1310     const_iv (FLAG_IS_USED_UP) const_iv (FLAG_IDENTIFIED) const_iv (FLAG_REFLECTING) const_iv (FLAG_CHANGING)
1311     const_iv (FLAG_SPLITTING) const_iv (FLAG_HITBACK) const_iv (FLAG_STARTEQUIP) const_iv (FLAG_BLOCKSVIEW)
1312     const_iv (FLAG_UNDEAD) const_iv (FLAG_SCARED) const_iv (FLAG_UNAGGRESSIVE) const_iv (FLAG_REFL_MISSILE)
1313     const_iv (FLAG_REFL_SPELL) const_iv (FLAG_NO_MAGIC) const_iv (FLAG_NO_FIX_PLAYER) const_iv (FLAG_IS_LIGHTABLE)
1314     const_iv (FLAG_TEAR_DOWN) const_iv (FLAG_RUN_AWAY) const_iv (FLAG_PICK_UP) const_iv (FLAG_UNIQUE)
1315     const_iv (FLAG_NO_DROP) const_iv (FLAG_WIZCAST) const_iv (FLAG_CAST_SPELL) const_iv (FLAG_USE_SCROLL)
1316     const_iv (FLAG_USE_RANGE) const_iv (FLAG_USE_BOW) const_iv (FLAG_USE_ARMOUR) const_iv (FLAG_USE_WEAPON)
1317     const_iv (FLAG_USE_RING) const_iv (FLAG_READY_RANGE) const_iv (FLAG_READY_BOW) const_iv (FLAG_XRAYS)
1318     const_iv (FLAG_NO_APPLY) const_iv (FLAG_IS_FLOOR) const_iv (FLAG_LIFESAVE) const_iv (FLAG_NO_STRENGTH)
1319     const_iv (FLAG_SLEEP) const_iv (FLAG_STAND_STILL) const_iv (FLAG_RANDOM_MOVE) const_iv (FLAG_ONLY_ATTACK)
1320     const_iv (FLAG_CONFUSED) const_iv (FLAG_STEALTH) const_iv (FLAG_WIZPASS) const_iv (FLAG_IS_LINKED)
1321     const_iv (FLAG_CURSED) const_iv (FLAG_DAMNED) const_iv (FLAG_SEE_ANYWHERE) const_iv (FLAG_KNOWN_MAGICAL)
1322     const_iv (FLAG_KNOWN_CURSED) const_iv (FLAG_CAN_USE_SKILL) const_iv (FLAG_BEEN_APPLIED) const_iv (FLAG_READY_SCROLL)
1323     const_iv (FLAG_USE_ROD) const_iv (FLAG_USE_HORN) const_iv (FLAG_MAKE_INVIS) const_iv (FLAG_INV_LOCKED)
1324     const_iv (FLAG_IS_WOODED) const_iv (FLAG_IS_HILLY) const_iv (FLAG_READY_SKILL) const_iv (FLAG_READY_WEAPON)
1325     const_iv (FLAG_NO_SKILL_IDENT) const_iv (FLAG_BLIND) const_iv (FLAG_SEE_IN_DARK) const_iv (FLAG_IS_CAULDRON)
1326     const_iv (FLAG_NO_STEAL) const_iv (FLAG_ONE_HIT) const_iv (FLAG_CLIENT_SENT) const_iv (FLAG_BERSERK)
1327     const_iv (FLAG_NEUTRAL) const_iv (FLAG_NO_ATTACK) const_iv (FLAG_NO_DAMAGE) const_iv (FLAG_OBJ_ORIGINAL)
1328 root 1.245 const_iv (FLAG_ACTIVATE_ON_PUSH) const_iv (FLAG_ACTIVATE_ON_RELEASE) const_iv (FLAG_IS_WATER)
1329 root 1.189 const_iv (FLAG_CONTENT_ON_GEN) const_iv (FLAG_IS_A_TEMPLATE) const_iv (FLAG_IS_BUILDABLE)
1330     const_iv (FLAG_DESTROY_ON_DEATH) const_iv (FLAG_NO_MAP_SAVE)
1331    
1332     const_iv (NDI_BLACK) const_iv (NDI_WHITE) const_iv (NDI_NAVY) const_iv (NDI_RED)
1333     const_iv (NDI_ORANGE) const_iv (NDI_BLUE) const_iv (NDI_DK_ORANGE) const_iv (NDI_GREEN)
1334     const_iv (NDI_LT_GREEN) const_iv (NDI_GREY) const_iv (NDI_BROWN) const_iv (NDI_GOLD)
1335     const_iv (NDI_TAN) const_iv (NDI_MAX_COLOR) const_iv (NDI_COLOR_MASK) const_iv (NDI_UNIQUE)
1336 root 1.241 const_iv (NDI_ALL) const_iv (NDI_DEF) const_iv (NDI_REPLY) const_iv (NDI_CLIENT_MASK)
1337 root 1.250 const_iv (NDI_NOCREATE) const_iv (NDI_CLEAR)
1338 root 1.1
1339 root 1.189 const_iv (UPD_LOCATION) const_iv (UPD_FLAGS) const_iv (UPD_WEIGHT) const_iv (UPD_FACE)
1340     const_iv (UPD_NAME) const_iv (UPD_ANIM) const_iv (UPD_ANIMSPEED) const_iv (UPD_NROF)
1341    
1342     const_iv (UPD_SP_MANA) const_iv (UPD_SP_GRACE) const_iv (UPD_SP_DAMAGE)
1343    
1344 root 1.212 const_iv (SP_RAISE_DEAD)
1345     const_iv (SP_RUNE)
1346     const_iv (SP_MAKE_MARK)
1347     const_iv (SP_BOLT)
1348     const_iv (SP_BULLET)
1349     const_iv (SP_EXPLOSION)
1350     const_iv (SP_CONE)
1351     const_iv (SP_BOMB)
1352     const_iv (SP_WONDER)
1353     const_iv (SP_SMITE)
1354     const_iv (SP_MAGIC_MISSILE)
1355     const_iv (SP_SUMMON_GOLEM)
1356     const_iv (SP_DIMENSION_DOOR)
1357     const_iv (SP_MAGIC_MAPPING)
1358     const_iv (SP_MAGIC_WALL)
1359     const_iv (SP_DESTRUCTION)
1360     const_iv (SP_PERCEIVE_SELF)
1361     const_iv (SP_WORD_OF_RECALL)
1362     const_iv (SP_INVISIBLE)
1363     const_iv (SP_PROBE)
1364     const_iv (SP_HEALING)
1365     const_iv (SP_CREATE_FOOD)
1366     const_iv (SP_EARTH_TO_DUST)
1367     const_iv (SP_CHANGE_ABILITY)
1368     const_iv (SP_BLESS)
1369     const_iv (SP_CURSE)
1370     const_iv (SP_SUMMON_MONSTER)
1371     const_iv (SP_CHARGING)
1372     const_iv (SP_POLYMORPH)
1373     const_iv (SP_ALCHEMY)
1374     const_iv (SP_REMOVE_CURSE)
1375     const_iv (SP_IDENTIFY)
1376     const_iv (SP_DETECTION)
1377     const_iv (SP_MOOD_CHANGE)
1378     const_iv (SP_MOVING_BALL)
1379     const_iv (SP_SWARM)
1380     const_iv (SP_CHANGE_MANA)
1381     const_iv (SP_DISPEL_RUNE)
1382     const_iv (SP_CREATE_MISSILE)
1383     const_iv (SP_CONSECRATE)
1384     const_iv (SP_ANIMATE_WEAPON)
1385     const_iv (SP_LIGHT)
1386     const_iv (SP_CHANGE_MAP_LIGHT)
1387     const_iv (SP_FAERY_FIRE)
1388     const_iv (SP_CAUSE_DISEASE)
1389     const_iv (SP_AURA)
1390     const_iv (SP_TOWN_PORTAL)
1391     const_iv (SP_PARTY_SPELL)
1392    
1393 root 1.189 const_iv (F_APPLIED) const_iv (F_LOCATION) const_iv (F_UNPAID) const_iv (F_MAGIC)
1394     const_iv (F_CURSED) const_iv (F_DAMNED) const_iv (F_OPEN) const_iv (F_NOPICK)
1395 root 1.1 const_iv (F_LOCKED)
1396    
1397 root 1.189 const_iv (F_BUY) const_iv (F_SHOP) const_iv (F_SELL)
1398    
1399     const_iv (P_BLOCKSVIEW) const_iv (P_PLAYER) const_iv (P_NO_MAGIC) const_iv (P_IS_ALIVE)
1400     const_iv (P_NO_CLERIC) const_iv (P_OUT_OF_MAP) const_iv (P_NEW_MAP) const_iv (P_UPTODATE)
1401    
1402     const_iv (UP_OBJ_INSERT) const_iv (UP_OBJ_REMOVE) const_iv (UP_OBJ_CHANGE) const_iv (UP_OBJ_FACE)
1403    
1404     const_iv (INS_NO_MERGE) const_iv (INS_ABOVE_FLOOR_ONLY) const_iv (INS_NO_WALK_ON)
1405 root 1.258 const_iv (INS_ON_TOP) const_iv (INS_BELOW_ORIGINATOR)
1406 root 1.189
1407     const_iv (WILL_APPLY_HANDLE) const_iv (WILL_APPLY_TREASURE) const_iv (WILL_APPLY_EARTHWALL)
1408     const_iv (WILL_APPLY_DOOR) const_iv (WILL_APPLY_FOOD)
1409    
1410     const_iv (SAVE_MODE) const_iv (SAVE_DIR_MODE)
1411    
1412     const_iv (M_PAPER) const_iv (M_IRON) const_iv (M_GLASS) const_iv (M_LEATHER)
1413     const_iv (M_WOOD) const_iv (M_ORGANIC) const_iv (M_STONE) const_iv (M_CLOTH)
1414     const_iv (M_ADAMANT) const_iv (M_LIQUID) const_iv (M_SOFT_METAL) const_iv (M_BONE)
1415     const_iv (M_ICE) const_iv (M_SPECIAL)
1416    
1417     const_iv (SK_EXP_ADD_SKILL) const_iv (SK_EXP_TOTAL) const_iv (SK_EXP_NONE)
1418     const_iv (SK_SUBTRACT_SKILL_EXP) const_iv (SK_EXP_SKILL_ONLY)
1419    
1420     const_iv (SK_LOCKPICKING) const_iv (SK_HIDING) const_iv (SK_SMITHERY) const_iv (SK_BOWYER)
1421     const_iv (SK_JEWELER) const_iv (SK_ALCHEMY) const_iv (SK_STEALING) const_iv (SK_LITERACY)
1422     const_iv (SK_BARGAINING) const_iv (SK_JUMPING) const_iv (SK_DET_MAGIC) const_iv (SK_ORATORY)
1423     const_iv (SK_SINGING) const_iv (SK_DET_CURSE) const_iv (SK_FIND_TRAPS) const_iv (SK_MEDITATION)
1424     const_iv (SK_PUNCHING) const_iv (SK_FLAME_TOUCH) const_iv (SK_KARATE) const_iv (SK_CLIMBING)
1425     const_iv (SK_WOODSMAN) const_iv (SK_INSCRIPTION) const_iv (SK_ONE_HANDED_WEAPON) const_iv (SK_MISSILE_WEAPON)
1426     const_iv (SK_THROWING) const_iv (SK_USE_MAGIC_ITEM) const_iv (SK_DISARM_TRAPS) const_iv (SK_SET_TRAP)
1427     const_iv (SK_THAUMATURGY) const_iv (SK_PRAYING) const_iv (SK_CLAWING) const_iv (SK_LEVITATION)
1428     const_iv (SK_SUMMONING) const_iv (SK_PYROMANCY) const_iv (SK_EVOCATION) const_iv (SK_SORCERY)
1429     const_iv (SK_TWO_HANDED_WEAPON) const_iv (SK_SPARK_TOUCH) const_iv (SK_SHIVER) const_iv (SK_ACID_SPLASH)
1430 root 1.1 const_iv (SK_POISON_NAIL)
1431    
1432 root 1.189 const_iv (SOUND_NEW_PLAYER) const_iv (SOUND_FIRE_ARROW) const_iv (SOUND_LEARN_SPELL) const_iv (SOUND_FUMBLE_SPELL)
1433     const_iv (SOUND_WAND_POOF) const_iv (SOUND_OPEN_DOOR) const_iv (SOUND_PUSH_PLAYER) const_iv (SOUND_PLAYER_HITS1)
1434     const_iv (SOUND_PLAYER_HITS2) const_iv (SOUND_PLAYER_HITS3) const_iv (SOUND_PLAYER_HITS4) const_iv (SOUND_PLAYER_IS_HIT1)
1435     const_iv (SOUND_PLAYER_IS_HIT2) const_iv (SOUND_PLAYER_IS_HIT3) const_iv (SOUND_PLAYER_KILLS) const_iv (SOUND_PET_IS_KILLED)
1436     const_iv (SOUND_PLAYER_DIES) const_iv (SOUND_OB_EVAPORATE) const_iv (SOUND_OB_EXPLODE) const_iv (SOUND_CLOCK)
1437     const_iv (SOUND_TURN_HANDLE) const_iv (SOUND_FALL_HOLE) const_iv (SOUND_DRINK_POISON) const_iv (SOUND_CAST_SPELL_0)
1438    
1439     const_iv (PREFER_LOW) const_iv (PREFER_HIGH)
1440    
1441     const_iv (ATNR_PHYSICAL) const_iv (ATNR_MAGIC) const_iv (ATNR_FIRE) const_iv (ATNR_ELECTRICITY)
1442     const_iv (ATNR_COLD) const_iv (ATNR_CONFUSION) const_iv (ATNR_ACID) const_iv (ATNR_DRAIN)
1443     const_iv (ATNR_WEAPONMAGIC) const_iv (ATNR_GHOSTHIT) const_iv (ATNR_POISON) const_iv (ATNR_SLOW)
1444     const_iv (ATNR_PARALYZE) const_iv (ATNR_TURN_UNDEAD) const_iv (ATNR_FEAR) const_iv (ATNR_CANCELLATION)
1445     const_iv (ATNR_DEPLETE) const_iv (ATNR_DEATH) const_iv (ATNR_CHAOS) const_iv (ATNR_COUNTERSPELL)
1446     const_iv (ATNR_GODPOWER) const_iv (ATNR_HOLYWORD) const_iv (ATNR_BLIND) const_iv (ATNR_INTERNAL)
1447     const_iv (ATNR_LIFE_STEALING) const_iv (ATNR_DISEASE)
1448    
1449 root 1.276 const_iv (MAP_ACTIVE) const_iv (MAP_SWAPPED) const_iv (MAP_LOADING) const_iv (MAP_SAVING)
1450     const_iv (MAP_INACTIVE)
1451 root 1.189
1452     const_iv (KLASS_ATTACHABLE) const_iv (KLASS_GLOBAL) const_iv (KLASS_OBJECT)
1453     const_iv (KLASS_CLIENT) const_iv (KLASS_PLAYER) const_iv (KLASS_MAP)
1454    
1455 root 1.251 const_iv (VERSION_CS) const_iv (VERSION_SC)
1456    
1457 root 1.189 const_iv (CS_QUERY_YESNO) const_iv (CS_QUERY_SINGLECHAR) const_iv (CS_QUERY_HIDEINPUT)
1458    
1459     const_iv (ST_DEAD) const_iv (ST_SETUP) const_iv (ST_PLAYING) const_iv (ST_CUSTOM)
1460 root 1.99
1461 root 1.189 const_iv (IO_HEADER) const_iv (IO_OBJECTS) const_iv (IO_UNIQUES)
1462 root 1.117
1463     // random map generator
1464 root 1.189 const_iv (LAYOUT_NONE) const_iv (LAYOUT_ONION) const_iv (LAYOUT_MAZE) const_iv (LAYOUT_SPIRAL)
1465     const_iv (LAYOUT_ROGUELIKE) const_iv (LAYOUT_SNAKE) const_iv (LAYOUT_SQUARE_SPIRAL)
1466    
1467     const_iv (RMOPT_RANDOM) const_iv (RMOPT_CENTERED) const_iv (RMOPT_LINEAR)
1468     const_iv (RMOPT_BOTTOM_C) const_iv (RMOPT_BOTTOM_R) const_iv (RMOPT_IRR_SPACE)
1469     const_iv (RMOPT_WALL_OFF) const_iv (RMOPT_WALLS_ONLY) const_iv (RMOPT_NO_DOORS)
1470    
1471     const_iv (SYMMETRY_RANDOM) const_iv (SYMMETRY_NONE) const_iv (SYMMETRY_X)
1472     const_iv (SYMMETRY_Y) const_iv (SYMMETRY_XY)
1473 root 1.195
1474     const_iv (GT_ENVIRONMENT) const_iv (GT_INVISIBLE) const_iv (GT_STARTEQUIP)
1475 root 1.281 const_iv (GT_APPLY) const_iv (GT_ONLY_GOOD) const_iv (GT_MINIMAL)
1476 root 1.238
1477     const_iv (FT_FACE) const_iv (FT_MUSIC) const_iv (FT_SOUND)
1478     const_iv (FT_RSRC) const_iv (FT_NUM)
1479 root 1.1 };
1480    
1481     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1482 root 1.109 newCONSTSUB (stash_cf, (char *)civ->name, newSViv (civ->iv));
1483 root 1.1
1484     static const struct {
1485     const char *name;
1486 root 1.14 int skip;
1487 root 1.7 IV klass;
1488 root 1.1 IV iv;
1489 root 1.6 } *eiv, event_iv[] = {
1490 root 1.14 # define def(klass,name) { "EVENT_" # klass "_" # name, sizeof ("EVENT_" # klass), (IV)KLASS_ ## klass, (IV)EVENT_ ## klass ## _ ## name },
1491 root 1.6 # include "eventinc.h"
1492     # undef def
1493     };
1494    
1495     AV *av = get_av ("cf::EVENT", 1);
1496    
1497     for (eiv = event_iv + sizeof (event_iv) / sizeof (event_iv [0]); eiv-- > event_iv; )
1498 root 1.7 {
1499     AV *event = newAV ();
1500 root 1.14 av_push (event, newSVpv ((char *)eiv->name + eiv->skip, 0));
1501 root 1.7 av_push (event, newSViv (eiv->klass));
1502     av_store (av, eiv->iv, newRV_noinc ((SV *)event));
1503 root 1.109 newCONSTSUB (stash_cf, (char *)eiv->name, newSViv (eiv->iv));
1504 root 1.7 }
1505 root 1.14 }
1506    
1507 root 1.109 void _connect_to_perl ()
1508 root 1.14
1509 root 1.210 void _recalc_want ()
1510    
1511 root 1.47 void _global_reattach ()
1512 root 1.14 CODE:
1513     {
1514     // reattach to all attachable objects in the game.
1515 root 1.128 for_all_clients (ns)
1516     ns->reattach ();
1517 root 1.96
1518 root 1.128 for_all_objects (op)
1519 root 1.109 op->reattach ();
1520 root 1.1 }
1521    
1522 root 1.192 # support function for map-world.ext
1523     void _quantise (SV *data_sv, SV *plt_sv)
1524     CODE:
1525     {
1526     if (!SvROK (plt_sv) || SvTYPE (SvRV (plt_sv)) != SVt_PVAV)
1527     croak ("_quantise called with invalid agruments");
1528    
1529     plt_sv = SvRV (plt_sv);
1530     SV **plt = AvARRAY (plt_sv);
1531     int plt_count = AvFILL (plt_sv) + 1;
1532    
1533     STRLEN len;
1534     char *data = SvPVbyte (data_sv, len);
1535     char *dst = data;
1536    
1537     while (len >= 3)
1538     {
1539     for (SV **val_sv = plt + plt_count; val_sv-- > plt; )
1540     {
1541     char *val = SvPVX (*val_sv);
1542    
1543     if (val [0] == data [0]
1544     && val [1] == data [1]
1545     && val [2] == data [2])
1546     {
1547     *dst++ = val [3];
1548     goto next;
1549     }
1550     }
1551    
1552     croak ("_quantise: color not found in palette: #%02x%02x%02x, at offset %d %d",
1553     (uint8_t)data [0], (uint8_t)data [1], (uint8_t)data [2],
1554     dst - SvPVX (data_sv), len);
1555    
1556     next:
1557     data += 3;
1558     len -= 3;
1559     }
1560    
1561     SvCUR_set (data_sv, dst - SvPVX (data_sv));
1562     }
1563    
1564 root 1.273 void evthread_start (int aiofd)
1565 root 1.272
1566     void cede_to_tick ()
1567 root 1.236 CODE:
1568 root 1.272 coroapi::cede_to_tick ();
1569 root 1.236
1570 root 1.272 NV till_tick ()
1571 root 1.236 CODE:
1572 root 1.272 RETVAL = SvNVX (sv_next_tick) - now ();
1573 root 1.236 OUTPUT:
1574     RETVAL
1575    
1576 root 1.272 int tick_inhibit ()
1577 root 1.236 CODE:
1578 root 1.272 RETVAL = tick_inhibit;
1579 root 1.236 OUTPUT:
1580     RETVAL
1581    
1582 root 1.272 void tick_inhibit_inc ()
1583     CODE:
1584     ++tick_inhibit;
1585    
1586     void tick_inhibit_dec ()
1587     CODE:
1588     if (!--tick_inhibit)
1589     if (tick_pending)
1590     {
1591     ev_async_send (EV_DEFAULT, &tick_watcher);
1592     coroapi::cede ();
1593     }
1594    
1595     void server_tick ()
1596     CODE:
1597     {
1598     NOW = ev_now (EV_DEFAULT);
1599     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1600     SvNV_set (sv_tick_start, NOW); SvNOK_only (sv_tick_start);
1601     runtime = SvNVX (sv_runtime);
1602    
1603     server_tick ();
1604    
1605     NOW = ev_time ();
1606     SvNV_set (sv_now, NOW); SvNOK_only (sv_now);
1607     runtime += TICK;
1608     SvNV_set (sv_runtime, runtime); SvNOK_only (sv_runtime);
1609     }
1610    
1611 root 1.1 NV floor (NV x)
1612    
1613     NV ceil (NV x)
1614    
1615 root 1.143 NV rndm (...)
1616 root 1.286 ALIAS:
1617     rmg_rndm = 1
1618 root 1.143 CODE:
1619 root 1.286 {
1620     rand_gen &gen = ix ? rmg_rndm : rndm;
1621 root 1.143 switch (items)
1622     {
1623 root 1.286 case 0: RETVAL = gen (); break;
1624     case 1: RETVAL = gen (SvUV (ST (0))); break;
1625     case 2: RETVAL = gen (SvIV (ST (0)), SvIV (ST (1))); break;
1626 root 1.143 default: croak ("cf::rndm requires none, one or two parameters."); break;
1627     }
1628 root 1.286 }
1629 root 1.143 OUTPUT:
1630     RETVAL
1631    
1632 root 1.207 NV clamp (NV value, NV min_value, NV max_value)
1633     CODE:
1634     RETVAL = clamp (value, min_value, max_value);
1635     OUTPUT:
1636     RETVAL
1637    
1638     NV lerp (NV value, NV min_in, NV max_in, NV min_out, NV max_out)
1639     CODE:
1640     RETVAL = lerp (value, min_in, max_in, min_out, max_out);
1641     OUTPUT:
1642     RETVAL
1643    
1644 root 1.268 void weaken (...)
1645     PROTOTYPE: @
1646     CODE:
1647     while (items > 0)
1648     sv_rvweaken (ST (--items));
1649    
1650 root 1.1 void
1651 root 1.198 log_backtrace (utf8_string msg)
1652    
1653     void
1654     LOG (int flags, utf8_string msg)
1655 root 1.1 PROTOTYPE: $$
1656 root 1.198 C_ARGS: flags, "%s", msg
1657 root 1.1
1658 root 1.183 octet_string path_combine (octet_string base, octet_string path)
1659 root 1.1 PROTOTYPE: $$
1660    
1661 root 1.183 octet_string path_combine_and_normalize (octet_string base, octet_string path)
1662 root 1.1 PROTOTYPE: $$
1663    
1664     void
1665     sub_generation_inc ()
1666     CODE:
1667     PL_sub_generation++;
1668    
1669 root 1.183 const_octet_string
1670 root 1.1 mapdir ()
1671     PROTOTYPE:
1672     ALIAS:
1673     mapdir = 0
1674     uniquedir = 1
1675     tmpdir = 2
1676     confdir = 3
1677     localdir = 4
1678     playerdir = 5
1679     datadir = 6
1680     CODE:
1681 root 1.19 switch (ix)
1682     {
1683     case 0: RETVAL = settings.mapdir ; break;
1684     case 1: RETVAL = settings.uniquedir; break;
1685     case 2: RETVAL = settings.tmpdir ; break;
1686     case 3: RETVAL = settings.confdir ; break;
1687     case 4: RETVAL = settings.localdir ; break;
1688     case 5: RETVAL = settings.playerdir; break;
1689     case 6: RETVAL = settings.datadir ; break;
1690     }
1691 root 1.1 OUTPUT: RETVAL
1692    
1693 root 1.120 void abort ()
1694    
1695 root 1.199 void reset_signals ()
1696    
1697 root 1.270 void fork_abort (const_octet_string cause = "cf::fork_abort")
1698 root 1.144
1699 root 1.270 void cleanup (const_octet_string cause, bool make_core = false)
1700 root 1.134
1701 root 1.116 void emergency_save ()
1702    
1703 root 1.156 void _exit (int status = EXIT_SUCCESS)
1704    
1705 root 1.125 #if _POSIX_MEMLOCK
1706    
1707     int mlockall (int flags = MCL_CURRENT | MCL_FUTURE)
1708 root 1.271 INIT:
1709 root 1.279 #if __GLIBC__
1710     mallopt (M_PERTURB, 0xee); // bug-workaround for linux glibc+mlockall+calloc
1711 root 1.277 #endif
1712 root 1.125
1713     int munlockall ()
1714    
1715     #endif
1716    
1717 root 1.279 int
1718     malloc_trim (IV pad = 0)
1719    
1720     void
1721     mallinfo ()
1722     PPCODE:
1723     {
1724     #if __GLIBC__
1725     struct mallinfo mai = mallinfo ();
1726     EXTEND (SP, 10*2);
1727     PUSHs (sv_2mortal (newSVpv ("arena" , 0))); PUSHs (sv_2mortal (newSViv (mai.arena)));
1728     PUSHs (sv_2mortal (newSVpv ("ordblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.ordblks)));
1729     PUSHs (sv_2mortal (newSVpv ("smblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.smblks)));
1730     PUSHs (sv_2mortal (newSVpv ("hblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblks)));
1731     PUSHs (sv_2mortal (newSVpv ("hblkhd" , 0))); PUSHs (sv_2mortal (newSViv (mai.hblkhd)));
1732     PUSHs (sv_2mortal (newSVpv ("usmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.usmblks)));
1733     PUSHs (sv_2mortal (newSVpv ("fsmblks" , 0))); PUSHs (sv_2mortal (newSViv (mai.fsmblks)));
1734     PUSHs (sv_2mortal (newSVpv ("uordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.uordblks)));
1735     PUSHs (sv_2mortal (newSVpv ("fordblks", 0))); PUSHs (sv_2mortal (newSViv (mai.fordblks)));
1736     PUSHs (sv_2mortal (newSVpv ("keepcost", 0))); PUSHs (sv_2mortal (newSViv (mai.keepcost)));
1737     #endif
1738     EXTEND (SP, 2*2);
1739     PUSHs (sv_2mortal (newSVpv ("slice_alloc", 0))); PUSHs (sv_2mortal (newSVuv (slice_alloc)));
1740     PUSHs (sv_2mortal (newSVpv ("shstr_alloc", 0))); PUSHs (sv_2mortal (newSVuv (shstr_alloc)));
1741 root 1.282 PUSHs (sv_2mortal (newSVpv ("objects" , 0))); PUSHs (sv_2mortal (newSVuv (objects.size () * sizeof (object))));
1742 root 1.279 }
1743    
1744 root 1.183 int find_animation (utf8_string text)
1745 root 1.1 PROTOTYPE: $
1746    
1747 root 1.74 int random_roll (int min, int max, object *op, int goodbad);
1748 root 1.1
1749 root 1.183 const_utf8_string cost_string_from_value(uint64 cost, int approx = 0)
1750 root 1.1
1751     int
1752     exp_to_level (val64 exp)
1753     CODE:
1754     {
1755     int i = 0;
1756    
1757     RETVAL = settings.max_level;
1758    
1759     for (i = 1; i <= settings.max_level; i++)
1760     {
1761     if (levels[i] > exp)
1762     {
1763     RETVAL = i - 1;
1764     break;
1765     }
1766     }
1767     }
1768     OUTPUT: RETVAL
1769    
1770     val64
1771     level_to_min_exp (int level)
1772     CODE:
1773     if (level > settings.max_level)
1774     RETVAL = levels[settings.max_level];
1775     else if (level < 1)
1776     RETVAL = 0;
1777     else
1778     RETVAL = levels[level];
1779     OUTPUT: RETVAL
1780    
1781     SV *
1782     resistance_to_string (int atnr)
1783     CODE:
1784     if (atnr >= 0 && atnr < NROFATTACKS)
1785     RETVAL = newSVpv (resist_plus[atnr], 0);
1786     else
1787     XSRETURN_UNDEF;
1788     OUTPUT: RETVAL
1789    
1790 root 1.275 UUID
1791 root 1.274 uuid_cur ()
1792     CODE:
1793 root 1.275 RETVAL = UUID::cur;
1794 root 1.274 OUTPUT:
1795     RETVAL
1796    
1797 root 1.275 UUID
1798 root 1.274 uuid_gen ()
1799     CODE:
1800 root 1.275 RETVAL = UUID::gen ();
1801     OUTPUT:
1802     RETVAL
1803    
1804     val64
1805     uuid_seq (UUID uuid)
1806     CODE:
1807     RETVAL = uuid.seq;
1808     OUTPUT:
1809     RETVAL
1810    
1811     UUID
1812     uuid_str (val64 seq)
1813     CODE:
1814     RETVAL.seq = seq;
1815 root 1.274 OUTPUT:
1816     RETVAL
1817    
1818     void
1819     coin_names ()
1820     PPCODE:
1821     EXTEND (SP, NUM_COINS);
1822     for (int i = 0; i < NUM_COINS; ++i)
1823     PUSHs (sv_2mortal (newSVpv (coins [i], 0)));
1824    
1825     void
1826     coin_archetypes ()
1827     PPCODE:
1828     EXTEND (SP, NUM_COINS);
1829     for (int i = 0; i < NUM_COINS; ++i)
1830     PUSHs (sv_2mortal (to_sv (archetype::find (coins [i]))));
1831    
1832 root 1.162 bool
1833 root 1.278 load_resource_file_ (octet_string filename)
1834 root 1.162
1835 root 1.288 void
1836     fix_weight ()
1837    
1838 root 1.97 MODULE = cf PACKAGE = cf::attachable
1839    
1840 root 1.27 int
1841 root 1.97 valid (SV *obj)
1842 root 1.27 CODE:
1843     RETVAL = SvROK (obj) && mg_find (SvRV (obj), PERL_MAGIC_ext);
1844     OUTPUT:
1845     RETVAL
1846    
1847 root 1.164 void
1848     debug_trace (attachable *obj, bool on = true)
1849     CODE:
1850     obj->flags &= ~attachable::F_DEBUG_TRACE;
1851     if (on)
1852     obj->flags |= attachable::F_DEBUG_TRACE;
1853    
1854 root 1.153 int mortals_size ()
1855     CODE:
1856     RETVAL = attachable::mortals.size ();
1857     OUTPUT: RETVAL
1858    
1859     #object *mortals (U32 index)
1860     # CODE:
1861     # RETVAL = index < attachable::mortals.size () ? attachable::mortals [index] : 0;
1862     # OUTPUT: RETVAL
1863    
1864 root 1.242 INCLUDE: $PERL $srcdir/genacc attachable ../include/util.h ../include/cfperl.h |
1865 root 1.115
1866 root 1.101 MODULE = cf PACKAGE = cf::global
1867    
1868     int invoke (SV *klass, int event, ...)
1869     CODE:
1870     if (KLASS_OF (event) != KLASS_GLOBAL) croak ("event class must be GLOBAL");
1871     AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1872     for (int i = 1; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1873 root 1.109 RETVAL = gbl_ev.invoke ((event_type)event, ARG_AV (av), DT_END);
1874 root 1.101 OUTPUT: RETVAL
1875    
1876 root 1.1 MODULE = cf PACKAGE = cf::object PREFIX = cf_object_
1877    
1878 root 1.173 INCLUDE: $PERL $srcdir/genacc object ../include/object.h |
1879 root 1.62
1880 root 1.18 int invoke (object *op, int event, ...)
1881     CODE:
1882     if (KLASS_OF (event) != KLASS_OBJECT) croak ("event class must be OBJECT");
1883 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
1884     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
1885 root 1.109 RETVAL = op->invoke ((event_type)event, ARG_AV (av), DT_END);
1886 root 1.18 OUTPUT: RETVAL
1887    
1888     SV *registry (object *op)
1889    
1890 root 1.134 int objects_size ()
1891     CODE:
1892     RETVAL = objects.size ();
1893     OUTPUT: RETVAL
1894    
1895     object *objects (U32 index)
1896     CODE:
1897     RETVAL = index < objects.size () ? objects [index] : 0;
1898     OUTPUT: RETVAL
1899    
1900     int actives_size ()
1901     CODE:
1902     RETVAL = actives.size ();
1903     OUTPUT: RETVAL
1904    
1905     object *actives (U32 index)
1906 root 1.57 CODE:
1907 root 1.134 RETVAL = index < actives.size () ? actives [index] : 0;
1908 root 1.57 OUTPUT: RETVAL
1909    
1910 root 1.283 int mortals_size ()
1911     CODE:
1912     RETVAL = attachable::mortals.size ();
1913     OUTPUT: RETVAL
1914    
1915 root 1.215 const char *slot_use_name (U32 slot)
1916 root 1.205 ALIAS:
1917 root 1.215 slot_nonuse_name = 1
1918 root 1.205 CODE:
1919     {
1920     if (slot >= NUM_BODY_LOCATIONS)
1921     croak ("body slot index out of range");
1922    
1923     switch (ix)
1924     {
1925 root 1.215 case 0: RETVAL = body_locations[slot].use_name; break;
1926     case 1: RETVAL = body_locations[slot].nonuse_name; break;
1927 root 1.205 }
1928     }
1929     OUTPUT:
1930     RETVAL
1931    
1932 root 1.1 # missing properties
1933    
1934 root 1.54 object *head (object *op)
1935     PROTOTYPE: $
1936     CODE:
1937 root 1.134 RETVAL = op->head_ ();
1938 root 1.54 OUTPUT: RETVAL
1939    
1940 root 1.1 void
1941     inv (object *obj)
1942     PROTOTYPE: $
1943     PPCODE:
1944     {
1945 root 1.254 for (object *o = obj->inv; o; o = o->below)
1946 root 1.100 XPUSHs (sv_2mortal (to_sv (o)));
1947 root 1.1 }
1948    
1949 root 1.102 void
1950     set_animation (object *op, int idx)
1951     CODE:
1952     SET_ANIMATION (op, idx);
1953    
1954 elmex 1.160 int
1955     num_animations (object *op)
1956     CODE:
1957     RETVAL = NUM_ANIMATIONS (op);
1958     OUTPUT: RETVAL
1959    
1960 root 1.205 int slot_info (object *op, UV slot, int value = 0)
1961     ALIAS:
1962     slot_used = 1
1963     CODE:
1964     {
1965     if (slot >= NUM_BODY_LOCATIONS)
1966     croak ("body slot index out of range");
1967    
1968 root 1.208 RETVAL = ix ? op->slot[slot].used : op->slot[slot].info;
1969 root 1.205
1970     if (items > 2)
1971     if (ix)
1972 root 1.208 op->slot[slot].used = value;
1973     else
1974 root 1.205 op->slot[slot].info = value;
1975     }
1976     OUTPUT:
1977     RETVAL
1978    
1979 root 1.183 object *find_best_object_match (object *op, utf8_string match)
1980 root 1.58
1981     object *find_marked_object (object *op)
1982    
1983 root 1.109 int need_identify (object *obj);
1984 root 1.1
1985     int apply_shop_mat (object *shop_mat, object *op);
1986    
1987 root 1.27 int move (object *op, int dir, object *originator = op)
1988     CODE:
1989     RETVAL = move_ob (op, dir, originator);
1990     OUTPUT:
1991     RETVAL
1992 root 1.1
1993 root 1.74 void apply (object *applier, object *applied, int flags = 0)
1994     CODE:
1995     manual_apply (applied, applier, flags);
1996 root 1.1
1997 root 1.74 void apply_below (object *op)
1998     CODE:
1999     player_apply_below (op);
2000 root 1.1
2001 root 1.167 int cast_heal (object *op, object *caster, object *spell, int dir = 0)
2002    
2003 root 1.74 int pay_item (object *op, object *buyer)
2004     CODE:
2005     RETVAL = pay_for_item (op, buyer);
2006     OUTPUT: RETVAL
2007 root 1.1
2008 root 1.74 int pay_amount (object *op, uint64 amount)
2009     CODE:
2010     RETVAL = pay_for_amount (amount, op);
2011     OUTPUT: RETVAL
2012 root 1.1
2013     void pay_player (object *op, uint64 amount)
2014    
2015 root 1.183 val64 pay_player_arch (object *op, utf8_string arch, uint64 amount)
2016 root 1.1
2017 root 1.183 int cast_spell (object *op, object *caster, int dir, object *spell_ob, utf8_string stringarg = 0)
2018 root 1.1
2019 root 1.74 void learn_spell (object *op, object *sp, int special_prayer = 0)
2020     CODE:
2021     do_learn_spell (op, sp, special_prayer);
2022 root 1.1
2023 root 1.74 void forget_spell (object *op, object *sp)
2024     CODE:
2025     do_forget_spell (op, query_name (sp));
2026 root 1.1
2027 root 1.183 object *check_for_spell (object *op, utf8_string spellname)
2028 root 1.74 CODE:
2029     RETVAL = check_spell_known (op, spellname);
2030     OUTPUT: RETVAL
2031 root 1.1
2032 root 1.74 int query_money (object *op)
2033 root 1.1 ALIAS: money = 0
2034    
2035 elmex 1.108 val64 query_cost (object *op, object *who, int flags)
2036 root 1.1 ALIAS: cost = 0
2037    
2038 root 1.74 void spring_trap (object *op, object *victim)
2039 root 1.1
2040 root 1.74 int check_trigger (object *op, object *cause)
2041 root 1.1
2042 root 1.74 void drop (object *who, object *op)
2043 root 1.1
2044 root 1.74 void pick_up (object *who, object *op)
2045 root 1.1
2046 root 1.102 void update_object (object *op, int action)
2047 root 1.1
2048 root 1.183 void change_exp (object *op, uint64 exp, utf8_string skill_name = 0, int flag = 0)
2049 root 1.1
2050     void player_lvl_adj (object *who, object *skill = 0)
2051    
2052     int kill_object (object *op, int dam = 0, object *hitter = 0, int type = AT_PHYSICAL)
2053    
2054     int calc_skill_exp (object *who, object *op, object *skill);
2055    
2056     void push_button (object *op);
2057    
2058     void use_trigger (object *op);
2059    
2060 root 1.61 void add_button_link (object *button, maptile *map, int connected);
2061 root 1.1
2062     void remove_button_link (object *op);
2063    
2064 elmex 1.232 void handle_apply_yield (object *op);
2065    
2066 root 1.1
2067     MODULE = cf PACKAGE = cf::object PREFIX = cf_
2068    
2069     # no clean way to get an object from an archetype - stupid idiotic
2070     # dumb kludgy misdesigned plug-in api slowly gets on my nerves.
2071    
2072 root 1.183 object *new (utf8_string archetype = 0)
2073 root 1.1 PROTOTYPE: ;$
2074     CODE:
2075 elmex 1.219 RETVAL = archetype ? get_archetype (archetype) : object::create ();
2076 root 1.1 OUTPUT:
2077     RETVAL
2078    
2079 root 1.225 object *find_object (U32 tag)
2080    
2081 root 1.218 # TODO: nuke
2082 root 1.61 object *insert_ob_in_map_at (object *ob, maptile *where, object_ornull *orig, int flag, int x, int y)
2083 root 1.1 PROTOTYPE: $$$$$$
2084     CODE:
2085     {
2086 root 1.257 RETVAL = insert_ob_in_map_at (ob, where, orig, flag, x, y);
2087 root 1.1 }
2088    
2089 root 1.284 shstr
2090     object::kv_get (shstr key)
2091 root 1.1
2092 root 1.284 void
2093     object::kv_del (shstr key)
2094    
2095     void
2096     object::kv_set (shstr key, shstr value)
2097 root 1.1
2098     object *get_nearest_player (object *ob)
2099     ALIAS: nearest_player = 0
2100     PREINIT:
2101     extern object *get_nearest_player (object *);
2102    
2103     void rangevector (object *ob, object *other, int flags = 0)
2104     PROTOTYPE: $$;$
2105     PPCODE:
2106     {
2107     rv_vector rv;
2108     get_rangevector (ob, other, &rv, flags);
2109     EXTEND (SP, 5);
2110     PUSHs (newSVuv (rv.distance));
2111     PUSHs (newSViv (rv.distance_x));
2112     PUSHs (newSViv (rv.distance_y));
2113     PUSHs (newSViv (rv.direction));
2114 root 1.257 PUSHs (to_sv (rv.part));
2115 root 1.1 }
2116    
2117     bool on_same_map_as (object *ob, object *other)
2118     CODE:
2119     RETVAL = on_same_map (ob, other);
2120     OUTPUT: RETVAL
2121    
2122 root 1.183 const_utf8_string
2123 root 1.58 base_name (object *op, int plural = op->nrof > 1)
2124 root 1.1 CODE:
2125 root 1.58 RETVAL = query_base_name (op, plural);
2126 root 1.1 OUTPUT: RETVAL
2127    
2128 root 1.256 # return the tail of an object, excluding itself
2129     void
2130     tail (object *op)
2131     PPCODE:
2132     while ((op = op->more))
2133     XPUSHs (sv_2mortal (to_sv (op)));
2134    
2135 root 1.1 MODULE = cf PACKAGE = cf::object::player PREFIX = cf_player_
2136    
2137     player *player (object *op)
2138     CODE:
2139     RETVAL = op->contr;
2140     OUTPUT: RETVAL
2141    
2142 root 1.257 bool move_player (object *op, int dir)
2143    
2144 root 1.105 void check_score (object *op)
2145    
2146 root 1.183 void message (object *op, utf8_string txt, int flags = NDI_ORANGE | NDI_UNIQUE)
2147 root 1.120 CODE:
2148     new_draw_info (flags, 0, op, txt);
2149 root 1.1
2150     void kill_player (object *op)
2151    
2152 root 1.257 void esrv_send_item (object *pl, object *item)
2153    
2154     void esrv_update_item (object *pl, int what, object *item)
2155     C_ARGS: what, pl, item
2156    
2157     void esrv_del_item (object *pl, int tag)
2158     C_ARGS: pl->contr, tag
2159 root 1.58
2160 root 1.183 int command_summon (object *op, utf8_string params)
2161 root 1.67
2162 root 1.183 int command_arrest (object *op, utf8_string params)
2163 root 1.67
2164 root 1.66
2165 root 1.12 MODULE = cf PACKAGE = cf::player PREFIX = cf_player_
2166 root 1.1
2167 root 1.173 INCLUDE: $PERL $srcdir/genacc player ../include/player.h |
2168 root 1.62
2169 root 1.18 int invoke (player *pl, int event, ...)
2170     CODE:
2171     if (KLASS_OF (event) != KLASS_PLAYER) croak ("event class must be PLAYER");
2172 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2173     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2174 root 1.109 RETVAL = pl->invoke ((event_type)event, ARG_AV (av), DT_END);
2175 root 1.18 OUTPUT: RETVAL
2176    
2177 root 1.12 SV *registry (player *pl)
2178 root 1.1
2179 root 1.102 void
2180     save_stats (player *pl)
2181     CODE:
2182     pl->ob->stats.hp = pl->ob->stats.maxhp;
2183     pl->ob->stats.sp = pl->ob->stats.maxsp;
2184     pl->ob->stats.grace = pl->ob->stats.maxgrace;
2185     pl->orig_stats = pl->ob->stats;
2186    
2187 root 1.217 void clear_los (player *pl)
2188    
2189 root 1.1 bool
2190     cell_visible (player *pl, int dx, int dy)
2191     CODE:
2192 root 1.98 RETVAL = FABS (dx) <= pl->ns->mapx / 2 && FABS (dy) <= pl->ns->mapy / 2
2193     && !pl->blocked_los [dx + pl->ns->mapx / 2][dy + pl->ns->mapy / 2];
2194 root 1.1 OUTPUT:
2195     RETVAL
2196    
2197 root 1.4 void
2198 root 1.1 send (player *pl, SV *packet)
2199     CODE:
2200     {
2201     STRLEN len;
2202     char *buf = SvPVbyte (packet, len);
2203    
2204 root 1.258 if (len > MAXSOCKBUF)
2205     pl->failmsg ("[packet too long for client]");
2206     else if (pl->ns)
2207 root 1.100 pl->ns->send_packet (buf, len);
2208 root 1.1 }
2209    
2210     int
2211     listening (player *pl, int new_value = -1)
2212     CODE:
2213     RETVAL = pl->listening;
2214     if (new_value >= 0)
2215     pl->listening = new_value;
2216     OUTPUT:
2217     RETVAL
2218    
2219 root 1.46 void savebed (player *pl, SV *map_path = 0, SV *x = 0, SV *y = 0)
2220 root 1.45 PROTOTYPE: $;$$$
2221 root 1.1 PPCODE:
2222 root 1.45 if (GIMME_V != G_VOID)
2223     {
2224     EXTEND (SP, 3);
2225     PUSHs (sv_2mortal (newSVpv (pl->savebed_map, 0)));
2226     PUSHs (sv_2mortal (newSViv (pl->bed_x)));
2227     PUSHs (sv_2mortal (newSViv (pl->bed_y)));
2228     }
2229 root 1.46 if (map_path) sv_to (map_path, pl->savebed_map);
2230     if (x) sv_to (x, pl->bed_x);
2231     if (y) sv_to (y, pl->bed_y);
2232 root 1.1
2233     void
2234     list ()
2235     PPCODE:
2236 root 1.128 for_all_players (pl)
2237 root 1.100 XPUSHs (sv_2mortal (to_sv (pl)));
2238 root 1.1
2239    
2240     MODULE = cf PACKAGE = cf::map PREFIX = cf_map_
2241    
2242 root 1.61 int invoke (maptile *map, int event, ...)
2243 root 1.18 CODE:
2244     if (KLASS_OF (event) != KLASS_MAP) croak ("event class must be MAP");
2245 root 1.24 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2246     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2247 root 1.109 RETVAL = map->invoke ((event_type)event, ARG_AV (av), DT_END);
2248 root 1.25 OUTPUT: RETVAL
2249 root 1.18
2250 root 1.61 SV *registry (maptile *map)
2251 root 1.12
2252 root 1.255 void
2253     find_tagged_objects (maptile *map, utf8_string tag = 0)
2254     PPCODE:
2255     {
2256     if (!map->spaces)
2257     XSRETURN_EMPTY;
2258    
2259     if (tag)
2260     {
2261     shstr_cmp tag_ (tag);
2262    
2263     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2264     for (object *op = ms->bot; op; op = op->above)
2265     if (op->tag == tag_)
2266     XPUSHs (sv_2mortal (to_sv (op)));
2267     }
2268     else
2269     {
2270     for (mapspace *ms = map->spaces + map->size (); ms-- > map->spaces; )
2271     for (object *op = ms->bot; op; op = op->above)
2272     if (op->tag)
2273     XPUSHs (sv_2mortal (to_sv (op)));
2274     }
2275     }
2276    
2277 root 1.173 INCLUDE: $PERL $srcdir/genacc maptile ../include/map.h |
2278 root 1.1
2279 root 1.116 void
2280     maptile::instantiate ()
2281    
2282     maptile *new ()
2283 root 1.1 PROTOTYPE:
2284     CODE:
2285 root 1.116 RETVAL = new maptile;
2286 root 1.1 OUTPUT:
2287     RETVAL
2288    
2289 root 1.116 void
2290 root 1.117 maptile::players ()
2291     PPCODE:
2292     if (GIMME_V == G_SCALAR)
2293 root 1.118 XPUSHs (sv_2mortal (to_sv (THIS->players)));
2294 root 1.117 else if (GIMME_V == G_ARRAY)
2295     {
2296     EXTEND (SP, THIS->players);
2297     for_all_players (pl)
2298     if (pl->ob && pl->ob->map == THIS)
2299 root 1.118 PUSHs (sv_2mortal (to_sv (pl->ob)));
2300 root 1.117 }
2301    
2302 root 1.156 void
2303 root 1.168 maptile::add_underlay (SV *data, int offset, int stride, SV *palette)
2304 root 1.156 CODE:
2305     {
2306 root 1.168 if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2307     croak ("maptile::add_underlay: palette must be arrayref");
2308 root 1.156
2309 root 1.168 palette = SvRV (palette);
2310 root 1.156
2311 root 1.168 STRLEN idxlen;
2312     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2313 root 1.156
2314 root 1.168 for (int x = 0; x < THIS->width; ++x)
2315     for (int y = 0; y < THIS->height; ++y)
2316     {
2317     for (object *op = THIS->at (x, y).bot; op; op = op->above)
2318     if (op->flag [FLAG_IS_FLOOR])
2319     goto skip_space;
2320    
2321     {
2322     int offs = offset + y * stride + x;
2323     if (IN_RANGE_EXC (offs, 0, idxlen))
2324     {
2325     if (SV **elem = av_fetch ((AV *)palette, idx [offs], 0))
2326     {
2327     object *ob = get_archetype (SvPVutf8_nolen (*elem));
2328     ob->flag [FLAG_NO_MAP_SAVE] = true;
2329     THIS->insert (ob, x, y, 0, INS_ABOVE_FLOOR_ONLY);
2330 root 1.200
2331     if (ob->randomitems)
2332     {
2333 root 1.203 if (!ob->above)
2334     {
2335     ob->create_treasure (ob->randomitems);
2336    
2337     for (object *op = ob->above; op; op = op->above)
2338     op->flag [FLAG_NO_MAP_SAVE] = true;
2339     }
2340    
2341 root 1.200 ob->randomitems = 0;
2342     }
2343 root 1.168 }
2344     }
2345     }
2346 root 1.156
2347 root 1.168 skip_space: ;
2348     }
2349     }
2350    
2351     void
2352     maptile::set_regiondata (SV *data, int offset, int stride, SV *palette)
2353     CODE:
2354     {
2355     if (!SvROK (palette) || SvTYPE (SvRV (palette)) != SVt_PVAV)
2356     croak ("maptile::set_regiondata: palette must be arrayref");
2357    
2358     palette = SvRV (palette);
2359    
2360     STRLEN idxlen;
2361     const uint8_t *idx = (const uint8_t *)SvPVbyte (data, idxlen);
2362    
2363 root 1.230 region_ptr *regionmap = new region_ptr [av_len ((AV *)palette) + 1];
2364 root 1.168 uint8_t *regions = salloc<uint8_t> (THIS->size ());
2365    
2366     for (int i = av_len ((AV *)palette) + 1; i--; )
2367 root 1.230 regionmap [i] = region::find (SvPVutf8_nolen (*av_fetch ((AV *)palette, i, 1)));
2368 root 1.168
2369     for (int y = 0; y < THIS->height; ++y)
2370     memcpy (regions + y * THIS->width, idx + offset + y * stride, THIS->width);
2371    
2372     sfree (THIS->regions, THIS->size ());
2373 root 1.230 delete [] THIS->regionmap;
2374 root 1.168
2375     THIS->regions = regions;
2376 root 1.156 THIS->regionmap = regionmap;
2377     }
2378    
2379 root 1.193 void
2380     maptile::create_region_treasure ()
2381     CODE:
2382     {
2383     object *op = object::create ();
2384     op->type = FLOOR;
2385     op->map = THIS;
2386    
2387     for (int x = 0; x < THIS->width; ++x)
2388     for (int y = 0; y < THIS->height; ++y)
2389     {
2390     region *rgn = THIS->region (x, y);
2391    
2392     //fprintf (stderr, "%d,%d %f %p\n", x, y, rgn->treasure_density,rgn->treasure);//D
2393     if (rgn->treasure && rndm () < rgn->treasure_density)
2394     {
2395     op->x = x;
2396     op->y = y;
2397     create_treasure (rgn->treasure, op, GT_ENVIRONMENT, THIS->difficulty);
2398     }
2399     }
2400    
2401     op->destroy ();
2402     }
2403    
2404 root 1.74 int out_of_map (maptile *map, int x, int y)
2405    
2406 root 1.29 void
2407 root 1.61 trigger (maptile *map, long connection, bool state = true)
2408 root 1.29 CODE:
2409     activate_connection (map, connection, state);
2410    
2411     void
2412 root 1.61 get_connection (maptile *map, long connection)
2413 root 1.29 PPCODE:
2414     oblinkpt *obp = get_connection_links (map, connection);
2415     if (obp)
2416     for (objectlink *ol = obp->link; ol; ol = ol->next)
2417 root 1.257 XPUSHs (sv_2mortal (to_sv ((object *)ol->ob)));
2418 root 1.1
2419     void
2420 root 1.140 get_map_flags (maptile *map, int x, int y)
2421 root 1.1 PPCODE:
2422     {
2423 root 1.61 maptile *nmap = 0;
2424 root 1.1 I16 nx = 0, ny = 0;
2425 root 1.19 int flags = get_map_flags (map, &nmap, x, y, &nx, &ny);
2426 root 1.1
2427     EXTEND (SP, 4);
2428     PUSHs (sv_2mortal (newSViv (flags)));
2429    
2430     if (GIMME_V == G_ARRAY)
2431     {
2432 root 1.257 PUSHs (sv_2mortal (to_sv (nmap)));
2433 root 1.1 PUSHs (sv_2mortal (newSViv (nx)));
2434     PUSHs (sv_2mortal (newSViv (ny)));
2435     }
2436     }
2437    
2438     void
2439 root 1.61 at (maptile *map, unsigned int x, unsigned int y)
2440 root 1.1 PROTOTYPE: $$$
2441     PPCODE:
2442     {
2443     object *o;
2444 root 1.61 maptile *nmap = 0;
2445 root 1.1 I16 nx, ny;
2446    
2447 root 1.19 get_map_flags (map, &nmap, x, y, &nx, &ny);
2448 root 1.1
2449     if (nmap)
2450     for (o = GET_MAP_OB (nmap, nx, ny); o; o = o->above)
2451 root 1.257 XPUSHs (sv_2mortal (to_sv (o)));
2452 root 1.1 }
2453    
2454     SV *
2455 root 1.61 bot_at (maptile *obj, unsigned int x, unsigned int y)
2456 root 1.1 PROTOTYPE: $$$
2457     ALIAS:
2458     top_at = 1
2459     flags_at = 2
2460     light_at = 3
2461     move_block_at = 4
2462     move_slow_at = 5
2463     move_on_at = 6
2464     move_off_at = 7
2465     INIT:
2466 root 1.110 if (x >= obj->width || y >= obj->height) XSRETURN_UNDEF;
2467 root 1.1 CODE:
2468     switch (ix)
2469     {
2470 root 1.257 case 0: RETVAL = to_sv (GET_MAP_OB (obj, x, y)); break;
2471     case 1: RETVAL = to_sv (GET_MAP_TOP (obj, x, y)); break;
2472     case 2: RETVAL = newSVuv (GET_MAP_FLAGS (obj, x, y)); break;
2473     case 3: RETVAL = newSViv (GET_MAP_LIGHT (obj, x, y)); break;
2474     case 4: RETVAL = newSVuv (GET_MAP_MOVE_BLOCK (obj, x, y)); break;
2475     case 5: RETVAL = newSVuv (GET_MAP_MOVE_SLOW (obj, x, y)); break;
2476     case 6: RETVAL = newSVuv (GET_MAP_MOVE_ON (obj, x, y)); break;
2477     case 7: RETVAL = newSVuv (GET_MAP_MOVE_OFF (obj, x, y)); break;
2478 root 1.1 }
2479 root 1.122 OUTPUT: RETVAL
2480 root 1.1
2481 elmex 1.70 void fix_walls (maptile *map, int x, int y)
2482    
2483     void fix_walls_around (maptile *map, int x, int y)
2484 root 1.1
2485 root 1.117 # worst xs function of my life
2486 root 1.140 bool
2487 root 1.117 _create_random_map (\
2488 root 1.140 maptile *self,\
2489 root 1.183 utf8_string wallstyle,\
2490     utf8_string wall_name,\
2491     utf8_string floorstyle,\
2492     utf8_string monsterstyle,\
2493     utf8_string treasurestyle,\
2494     utf8_string layoutstyle,\
2495     utf8_string doorstyle,\
2496     utf8_string decorstyle,\
2497     utf8_string origin_map,\
2498     utf8_string final_map,\
2499     utf8_string exitstyle,\
2500     utf8_string this_map,\
2501     utf8_string exit_on_final_map,\
2502 root 1.146 int xsize,\
2503     int ysize,\
2504 root 1.117 int expand2x,\
2505     int layoutoptions1,\
2506     int layoutoptions2,\
2507     int layoutoptions3,\
2508     int symmetry,\
2509     int difficulty,\
2510     int difficulty_given,\
2511     float difficulty_increase,\
2512     int dungeon_level,\
2513     int dungeon_depth,\
2514     int decoroptions,\
2515     int orientation,\
2516     int origin_y,\
2517     int origin_x,\
2518 root 1.146 U32 random_seed,\
2519 root 1.117 val64 total_map_hp,\
2520     int map_layout_style,\
2521     int treasureoptions,\
2522     int symmetry_used,\
2523 root 1.137 region *region,\
2524 root 1.183 utf8_string custom\
2525 root 1.117 )
2526     CODE:
2527     {
2528     random_map_params rmp;
2529    
2530     assign (rmp.wallstyle , wallstyle);
2531     assign (rmp.wall_name , wall_name);
2532     assign (rmp.floorstyle , floorstyle);
2533     assign (rmp.monsterstyle , monsterstyle);
2534     assign (rmp.treasurestyle , treasurestyle);
2535     assign (rmp.layoutstyle , layoutstyle);
2536     assign (rmp.doorstyle , doorstyle);
2537     assign (rmp.decorstyle , decorstyle);
2538     assign (rmp.exitstyle , exitstyle);
2539     assign (rmp.exit_on_final_map, exit_on_final_map);
2540    
2541 root 1.122 rmp.origin_map = origin_map;
2542     rmp.final_map = final_map;
2543     rmp.this_map = this_map;
2544 root 1.146 rmp.xsize = xsize;
2545     rmp.ysize = ysize;
2546 root 1.117 rmp.expand2x = expand2x;
2547     rmp.layoutoptions1 = layoutoptions1;
2548     rmp.layoutoptions2 = layoutoptions2;
2549     rmp.layoutoptions3 = layoutoptions3;
2550     rmp.symmetry = symmetry;
2551     rmp.difficulty = difficulty;
2552     rmp.difficulty_given = difficulty_given;
2553     rmp.difficulty_increase = difficulty_increase;
2554     rmp.dungeon_level = dungeon_level;
2555     rmp.dungeon_depth = dungeon_depth;
2556     rmp.decoroptions = decoroptions;
2557     rmp.orientation = orientation;
2558     rmp.origin_y = origin_y;
2559     rmp.origin_x = origin_x;
2560     rmp.random_seed = random_seed;
2561 root 1.214 rmp.total_map_hp = (uint64_t) total_map_hp;
2562 root 1.117 rmp.map_layout_style = map_layout_style;
2563     rmp.treasureoptions = treasureoptions;
2564     rmp.symmetry_used = symmetry_used;
2565     rmp.region = region;
2566 root 1.137 rmp.custom = custom;
2567 root 1.117
2568 root 1.140 RETVAL = self->generate_random_map (&rmp);
2569 root 1.117 }
2570     OUTPUT:
2571     RETVAL
2572    
2573 root 1.19 MODULE = cf PACKAGE = cf::arch
2574 root 1.1
2575 root 1.218 int archetypes_size ()
2576     CODE:
2577     RETVAL = archetypes.size ();
2578     OUTPUT: RETVAL
2579    
2580     archetype *archetypes (U32 index)
2581     CODE:
2582     RETVAL = index < archetypes.size () ? archetypes [index] : 0;
2583     OUTPUT: RETVAL
2584 root 1.1
2585 root 1.212 object *instantiate (archetype *arch)
2586     CODE:
2587     RETVAL = arch_to_object (arch);
2588     OUTPUT:
2589     RETVAL
2590    
2591 root 1.173 INCLUDE: $PERL $srcdir/genacc archetype ../include/object.h |
2592 root 1.1
2593 root 1.19 MODULE = cf PACKAGE = cf::party
2594 root 1.1
2595 root 1.19 partylist *first ()
2596 root 1.1 PROTOTYPE:
2597 root 1.19 CODE:
2598     RETVAL = get_firstparty ();
2599     OUTPUT: RETVAL
2600 root 1.1
2601 root 1.173 INCLUDE: $PERL $srcdir/genacc partylist ../include/player.h |
2602 root 1.1
2603 root 1.19 MODULE = cf PACKAGE = cf::region
2604 root 1.1
2605 root 1.161 void
2606     list ()
2607     PPCODE:
2608     for_all_regions (rgn)
2609     XPUSHs (sv_2mortal (to_sv (rgn)));
2610    
2611 root 1.183 region *find (utf8_string name)
2612 root 1.161 PROTOTYPE: $
2613 root 1.19 CODE:
2614 root 1.161 RETVAL = region::find (name);
2615 root 1.19 OUTPUT: RETVAL
2616 root 1.1
2617 root 1.183 region *find_fuzzy (utf8_string name)
2618 root 1.122 PROTOTYPE: $
2619     CODE:
2620 root 1.161 RETVAL = region::find_fuzzy (name);
2621 root 1.122 OUTPUT: RETVAL
2622    
2623 root 1.186 int specificity (region *rgn)
2624     CODE:
2625     RETVAL = 0;
2626     while (rgn = rgn->parent)
2627     RETVAL++;
2628     OUTPUT: RETVAL
2629    
2630 root 1.193 INCLUDE: $PERL $srcdir/genacc region ../include/region.h |
2631 root 1.1
2632 root 1.19 MODULE = cf PACKAGE = cf::living
2633 root 1.1
2634 root 1.173 INCLUDE: $PERL $srcdir/genacc living ../include/living.h |
2635 root 1.1
2636 root 1.76 MODULE = cf PACKAGE = cf::settings
2637    
2638 root 1.173 INCLUDE: $PERL $srcdir/genacc Settings ../include/global.h |
2639 root 1.76
2640 root 1.84 MODULE = cf PACKAGE = cf::client
2641 root 1.79
2642 root 1.173 INCLUDE: $PERL $srcdir/genacc client ../include/client.h |
2643 root 1.79
2644 root 1.84 int invoke (client *ns, int event, ...)
2645 root 1.79 CODE:
2646 root 1.88 if (KLASS_OF (event) != KLASS_CLIENT) croak ("event class must be CLIENT");
2647 root 1.79 AV *av = (AV *)sv_2mortal ((SV *)newAV ());
2648     for (int i = 2; i < items; i++) av_push (av, SvREFCNT_inc (ST (i)));
2649 root 1.109 RETVAL = ns->invoke ((event_type)event, ARG_AV (av), DT_END);
2650 root 1.79 OUTPUT: RETVAL
2651    
2652 root 1.84 SV *registry (client *ns)
2653 root 1.79
2654 root 1.100 void
2655     list ()
2656     PPCODE:
2657     EXTEND (SP, clients.size ());
2658     for (sockvec::iterator i = clients.begin (); i != clients.end (); ++i)
2659     PUSHs (sv_2mortal (to_sv (*i)));
2660    
2661 root 1.88 void
2662 root 1.100 client::send_packet (SV *packet)
2663     CODE:
2664     {
2665     STRLEN len;
2666     char *buf = SvPVbyte (packet, len);
2667    
2668 root 1.258 if (len > MAXSOCKBUF)
2669     {
2670     // ugly
2671     if (THIS->pl)
2672     THIS->pl->failmsg ("[packet too long for client]");
2673     }
2674     else
2675     THIS->send_packet (buf, len);
2676 root 1.100 }
2677    
2678 root 1.237 faceidx
2679 root 1.238 client::need_face (utf8_string name, int pri = 0)
2680 root 1.237 CODE:
2681 root 1.238 RETVAL = face_find (name, 0);
2682     if (RETVAL)
2683     {
2684     THIS->send_face (RETVAL, pri);
2685     THIS->flush_fx ();
2686     }
2687     OUTPUT:
2688     RETVAL
2689    
2690     int
2691     client::fx_want (int idx, int value = -1)
2692     CODE:
2693     if (0 < idx && idx < FT_NUM)
2694     {
2695     RETVAL = THIS->fx_want [idx];
2696     if (items > 2)
2697     THIS->fx_want [idx] = value;
2698     }
2699     else
2700     RETVAL = 0;
2701 root 1.237 OUTPUT:
2702     RETVAL
2703    
2704 root 1.239 MODULE = cf PACKAGE = cf::sound PREFIX = sound_
2705    
2706     faceidx sound_find (utf8_string name)
2707    
2708 root 1.240 void sound_set (utf8_string str, faceidx face)
2709    
2710     # dire hack
2711     void old_sound_index (int idx, faceidx face)
2712     CODE:
2713     extern faceidx old_sound_index [SOUND_CAST_SPELL_0];
2714     old_sound_index [idx] = face;
2715    
2716 root 1.176 MODULE = cf PACKAGE = cf::face PREFIX = face_
2717    
2718 root 1.185 #INCLUDE: $PERL $srcdir/genacc faceset ../include/face.h |
2719 root 1.176
2720 root 1.183 faceidx face_find (utf8_string name, faceidx defidx = 0)
2721 root 1.176
2722 root 1.183 faceidx alloc (utf8_string name)
2723 root 1.176 CODE:
2724     {
2725     do
2726     {
2727     RETVAL = faces.size ();
2728 root 1.177 faces.resize (RETVAL + 1);
2729 root 1.176 }
2730     while (!RETVAL); // crude way to leave index 0
2731    
2732     faces [RETVAL].name = name;
2733     facehash.insert (std::make_pair (faces [RETVAL].name, RETVAL));
2734    
2735     if (!strcmp (name, BLANK_FACE_NAME)) blank_face = RETVAL;
2736     if (!strcmp (name, EMPTY_FACE_NAME)) empty_face = RETVAL;
2737     }
2738     OUTPUT: RETVAL
2739    
2740 root 1.227 void set_type (faceidx idx, int value)
2741     ALIAS:
2742     set_type = 0
2743     set_visibility = 1
2744     set_magicmap = 2
2745     set_smooth = 3
2746     set_smoothlevel = 4
2747 root 1.176 CODE:
2748 root 1.229 faceinfo *f = face_info (idx); assert (f);
2749 root 1.227 switch (ix)
2750     {
2751     case 0: f->type = value; break;
2752     case 1: f->visibility = value; break;
2753     case 2: f->magicmap = value; break;
2754     case 3: f->smooth = value; break;
2755     case 4: f->smoothlevel = value; break;
2756     }
2757 root 1.177
2758     void set_data (faceidx idx, int faceset, SV *data, SV *chksum)
2759 root 1.176 CODE:
2760 root 1.182 {
2761 root 1.231 faceinfo *f = face_info (idx); assert (f);
2762     facedata *d = &(faceset ? f->data64 : f->data32);
2763 root 1.181 sv_to (data, d->data);
2764     STRLEN clen;
2765     char *cdata = SvPVbyte (chksum, clen);
2766 root 1.182 clen = min (CHKSUM_SIZE, clen);
2767    
2768     if (memcmp (d->chksum, cdata, clen))
2769     {
2770     memcpy (d->chksum, cdata, clen);
2771    
2772     // invalidate existing client face info
2773     for_all_clients (ns)
2774     if (ns->faceset == faceset)
2775     {
2776     ns->faces_sent [idx] = false;
2777     ns->force_newmap = true;
2778     }
2779     }
2780     }
2781 root 1.176
2782 root 1.229 int get_data_size (faceidx idx, int faceset = 0)
2783     CODE:
2784 root 1.267 facedata *d = face_data (idx, faceset);
2785     if (!d) XSRETURN_UNDEF;
2786 root 1.229 RETVAL = d->data.size ();
2787     OUTPUT:
2788     RETVAL
2789    
2790     SV *get_chksum (faceidx idx, int faceset = 0)
2791     CODE:
2792 root 1.267 facedata *d = face_data (idx, faceset);
2793     if (!d) XSRETURN_UNDEF;
2794 root 1.229 RETVAL = newSVpvn ((char *)d->chksum, CHKSUM_SIZE);
2795     OUTPUT:
2796     RETVAL
2797    
2798 root 1.267 SV *get_data (faceidx idx, int faceset = 0)
2799     CODE:
2800     facedata *d = face_data (idx, faceset);
2801     if (!d) XSRETURN_UNDEF;
2802     RETVAL = newSVpvn (d->data.data (), d->data.length ());
2803     OUTPUT:
2804     RETVAL
2805    
2806 root 1.177 void invalidate (faceidx idx)
2807     CODE:
2808     for_all_clients (ns)
2809 root 1.182 {
2810     ns->faces_sent [idx] = false;
2811     ns->force_newmap = true;
2812     }
2813 root 1.177
2814     void invalidate_all ()
2815     CODE:
2816     for_all_clients (ns)
2817 root 1.182 {
2818     ns->faces_sent.reset ();
2819     ns->force_newmap = true;
2820     }
2821 root 1.177
2822 root 1.185 MODULE = cf PACKAGE = cf::anim PREFIX = anim_
2823    
2824     #INCLUDE: $PERL $srcdir/genacc faceset ../include/anim.h |
2825    
2826     animidx anim_find (utf8_string name)
2827     CODE:
2828     RETVAL = animation::find (name).number;
2829     OUTPUT: RETVAL
2830    
2831     animidx set (utf8_string name, SV *frames, int facings = 1)
2832     CODE:
2833     {
2834     if (!SvROK (frames) && SvTYPE (SvRV (frames)) != SVt_PVAV)
2835     croak ("frames must be an arrayref");
2836    
2837     AV *av = (AV *)SvRV (frames);
2838    
2839     animation *anim = &animation::find (name);
2840     if (anim->number)
2841     {
2842     anim->resize (av_len (av) + 1);
2843     anim->facings = facings;
2844     }
2845     else
2846     anim = &animation::create (name, av_len (av) + 1, facings);
2847    
2848     for (int i = 0; i < anim->num_animations; ++i)
2849     anim->faces [i] = face_find (SvPVutf8_nolen (*av_fetch (av, i, 1)));
2850     }
2851     OUTPUT: RETVAL
2852    
2853     void invalidate_all ()
2854     CODE:
2855     for_all_clients (ns)
2856     ns->anims_sent.reset ();
2857    
2858 root 1.247 MODULE = cf PACKAGE = cf::object::freezer
2859    
2860     INCLUDE: $PERL $srcdir/genacc object_freezer ../include/cfperl.h |
2861    
2862     SV *
2863     new (char *klass)
2864     CODE:
2865     RETVAL = newSVptr (new object_freezer, gv_stashpv ("cf::object::freezer", 1));
2866     OUTPUT: RETVAL
2867    
2868     void
2869     DESTROY (SV *sv)
2870     CODE:
2871     object_freezer *self;
2872     sv_to (sv, self);
2873     delete self;
2874    
2875     MODULE = cf PACKAGE = cf::object::thawer
2876    
2877     INCLUDE: $PERL $srcdir/genacc object_thawer ../include/cfperl.h |
2878    
2879     SV *
2880     new_from_file (char *klass, octet_string path)
2881     CODE:
2882     object_thawer *f = new object_thawer (path);
2883     if (!*f)
2884     {
2885     delete f;
2886     XSRETURN_UNDEF;
2887     }
2888     RETVAL = newSVptr (f, gv_stashpv ("cf::object::thawer", 1));
2889     OUTPUT: RETVAL
2890    
2891     void
2892     DESTROY (SV *sv)
2893     CODE:
2894     object_thawer *self;
2895     sv_to (sv, self);
2896     delete self;
2897    
2898 root 1.252 void
2899 root 1.253 extract_tags (object_thawer *self)
2900 root 1.254 PPCODE:
2901 root 1.252 while (self->kw != KW_EOF)
2902     {
2903 root 1.254 PUTBACK;
2904 root 1.272 coroapi::cede_to_tick ();
2905 root 1.254 SPAGAIN;
2906 root 1.253
2907 root 1.252 if (self->kw == KW_tag)
2908 root 1.254 XPUSHs (sv_2mortal (newSVpv_utf8 (self->get_str ())));
2909 root 1.252
2910     self->skip ();
2911     }
2912