ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/cfperl.xs
Revision: 1.294
Committed: Fri Aug 29 02:07:09 2008 UTC (15 years, 9 months ago) by root
Branch: MAIN
Changes since 1.293: +0 -9 lines
Log Message:
remove listen(ing)?

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