ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/main.C
Revision: 1.112
Committed: Sun Jul 1 05:00:20 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.111: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.108 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3     *
4     * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2001-2003,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7     *
8 root 1.112 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * 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.108 *
13 root 1.112 * 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.108 *
18 root 1.112 * 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.108 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 root 1.84 */
23 elmex 1.1
24     #include <global.h>
25     #include <object.h>
26     #include <tod.h>
27    
28 root 1.47 #include <sproto.h>
29     #include <time.h>
30 elmex 1.1
31     #include <../random_maps/random_map.h>
32     #include <../random_maps/rproto.h>
33     #include "path.h"
34    
35     static char days[7][4] = {
36 root 1.20 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
37     };
38 elmex 1.1
39 root 1.20 void
40 root 1.23 version (object *op)
41 root 1.20 {
42 root 1.71 new_draw_info_format (NDI_UNIQUE, 0, op, "This is Crossfire+ v%s", VERSION);
43 root 1.63
44 root 1.20 new_draw_info (NDI_UNIQUE, 0, op, "Authors and contributors to this program:");
45 root 1.63 new_draw_info (NDI_UNIQUE, 0, op, "Marc A. Lehmann <pcg@goof.com>");
46     new_draw_info (NDI_UNIQUE, 0, op, "Robin Redeker <elmex@x-paste.de>");
47     new_draw_info (NDI_UNIQUE, 0, op, "Pippijn van Steenhoven <pip88nl@gmail.com>");
48 root 1.84 new_draw_info (NDI_UNIQUE, 0, op, "");
49     new_draw_info (NDI_UNIQUE, 0, op, "Authors and contributors to the original Crossfire:");
50 root 1.63 new_draw_info (NDI_UNIQUE, 0, op, "Mark Wedel <mwedel@sonic.net>");
51     new_draw_info (NDI_UNIQUE, 0, op, "Frank Tore Johansen <frankj@ifi.uio.no>");
52     new_draw_info (NDI_UNIQUE, 0, op, "Kjetil Torgrim Homme <kjetilho@ifi.uio.no>");
53     new_draw_info (NDI_UNIQUE, 0, op, "Tyler Van Gorder <tvangod@ecst.csuchico.edu>");
54     new_draw_info (NDI_UNIQUE, 0, op, "Tony Elmroth <elmroth@cd.chalmers.se>");
55     new_draw_info (NDI_UNIQUE, 0, op, "Dougal Scott <dougal.scott@fcit.monasu.edu.au>");
56     new_draw_info (NDI_UNIQUE, 0, op, "William <wchuang@athena.mit.edu>");
57     new_draw_info (NDI_UNIQUE, 0, op, "Geoff Bailey <ftww@cs.su.oz.au>");
58 root 1.71 new_draw_info (NDI_UNIQUE, 0, op, "Kjetil Wiekhorst Jørgensen <jorgens@flipper.pvv.unit.no>");
59 root 1.63 new_draw_info (NDI_UNIQUE, 0, op, "Cameron Blackwood <c.blackwood@rdt.monash.edu.au>");
60     new_draw_info (NDI_UNIQUE, 0, op, "Joseph L. Traub <jtraub+@cmu.edu>");
61     new_draw_info (NDI_UNIQUE, 0, op, "Rupert G. Goldie <rgg@aaii.oz.au>");
62     new_draw_info (NDI_UNIQUE, 0, op, "Eric A. Anderson <eanders+@cmu.edu>");
63     new_draw_info (NDI_UNIQUE, 0, op, "Rickard Eneqvist <eneq@Prag.DoCS.UU.SE>");
64     new_draw_info (NDI_UNIQUE, 0, op, "Jarkko Sonninen <Jarkko.Sonninen@lut.fi>");
65     new_draw_info (NDI_UNIQUE, 0, op, "Karl Holland <kholland@sunlab.cit.cornell.du>");
66     new_draw_info (NDI_UNIQUE, 0, op, "Mikael Lundgren <vick@bern.docs.uu.se>");
67     new_draw_info (NDI_UNIQUE, 0, op, "Mikael Olsson <mol@meryl.csd.uu.se>");
68     new_draw_info (NDI_UNIQUE, 0, op, "Tero Haatanen <Tero.Haatanen@lut.fi>");
69     new_draw_info (NDI_UNIQUE, 0, op, "Lasse Ylitalo <ylitalo@student.docs.uu.se>");
70     new_draw_info (NDI_UNIQUE, 0, op, "Niilo Neuvo <anipa@guru.magic.fi>");
71     new_draw_info (NDI_UNIQUE, 0, op, "Markku J{rvinen <mta@modeemi.cs.tut.fi>");
72     new_draw_info (NDI_UNIQUE, 0, op, "Sylvain Meunier <meunier@inf.enst.fr>");
73     new_draw_info (NDI_UNIQUE, 0, op, "Jason Fosback <jfosback@darmok.uoregon.edu>");
74     new_draw_info (NDI_UNIQUE, 0, op, "Carl Edman <cedman@capitalist.princeton.edu>");
75     new_draw_info (NDI_UNIQUE, 0, op, "Charles Henrich <henrich@crh.cl.msu.edu>");
76     new_draw_info (NDI_UNIQUE, 0, op, "Gregor Schmid <schmid@fb3-s7.math.tu-berlin.de>");
77     new_draw_info (NDI_UNIQUE, 0, op, "Raphael Quinet <quinet@montefiore.ulg.ac.be>");
78     new_draw_info (NDI_UNIQUE, 0, op, "Jari Vanhala <jam@modeemi.cs.tut.fi>");
79     new_draw_info (NDI_UNIQUE, 0, op, "Tero Kivinen <kivinen@joker.cs.hut.fi>");
80     new_draw_info (NDI_UNIQUE, 0, op, "Peter Mardahl <peterm@soda.berkeley.edu>");
81     new_draw_info (NDI_UNIQUE, 0, op, "Matthew Zeher <matt@cs.odu.edu>");
82     new_draw_info (NDI_UNIQUE, 0, op, "Scott R. Turner <srt@sun-dimas.aero.org>");
83     new_draw_info (NDI_UNIQUE, 0, op, "Ben Fennema <huma@netcom.com>");
84     new_draw_info (NDI_UNIQUE, 0, op, "Nick Williams <njw@cs.city.ac.uk>");
85     new_draw_info (NDI_UNIQUE, 0, op, "Laurent Wacrenier <Wacren@Gin.ObsPM.Fr>");
86     new_draw_info (NDI_UNIQUE, 0, op, "Brian Thomas <thomas@astro.psu.edu>");
87     new_draw_info (NDI_UNIQUE, 0, op, "John Steven Moerk <jsm@axon.ksc.nasa.gov>");
88     new_draw_info (NDI_UNIQUE, 0, op, "Delbecq David <david.delbecq@mailandnews.com>");
89     new_draw_info (NDI_UNIQUE, 0, op, "Chachkoff Yann <yann.chachkoff@mailandnews.com>\n");
90 root 1.84 new_draw_info (NDI_UNIQUE, 0, op, "");
91 root 1.20 new_draw_info (NDI_UNIQUE, 0, op, "Images and art:");
92     new_draw_info (NDI_UNIQUE, 0, op, "Peter Gardner");
93 root 1.63 new_draw_info (NDI_UNIQUE, 0, op, "David Gervais <david_eg@mail.com>");
94     new_draw_info (NDI_UNIQUE, 0, op, "Mitsuhiro Itakura <ita@gold.koma.jaeri.go.jp>");
95     new_draw_info (NDI_UNIQUE, 0, op, "Hansjoerg Malthaner <hansjoerg.malthaner@danet.de>");
96     new_draw_info (NDI_UNIQUE, 0, op, "Mårten Woxberg <maxmc@telia.com>");
97 root 1.84 new_draw_info (NDI_UNIQUE, 0, op, "");
98 root 1.20 new_draw_info (NDI_UNIQUE, 0, op, "And many more!");
99     }
100    
101 elmex 1.1 /* This is a basic little function to put the player back to his
102     * savebed. We do some error checking - its possible that the
103     * savebed map may no longer exist, so we make sure the player
104     * goes someplace.
105     */
106 root 1.20 void
107 root 1.23 enter_player_savebed (object *op)
108 elmex 1.1 {
109 root 1.63 object *tmp = object::create ();
110 root 1.20 EXIT_PATH (tmp) = op->contr->savebed_map;
111     EXIT_X (tmp) = op->contr->bed_x;
112     EXIT_Y (tmp) = op->contr->bed_y;
113 root 1.62 op->enter_exit (tmp);
114 root 1.41 tmp->destroy ();
115 elmex 1.1 }
116    
117     /*
118 root 1.62 * enter_map(): Moves the player and pets from current map (if any) to
119 elmex 1.1 * new map. map, x, y must be set. map is the map we are moving the
120     * player to - it could be the map he just came from if the load failed for
121     * whatever reason. If default map coordinates are to be used, then
122     * the function that calls this should figure them out.
123     */
124 root 1.62 void
125     object::enter_map (maptile *newmap, int x, int y)
126 root 1.20 {
127 root 1.72 if (destroyed () || !newmap || newmap->in_memory != MAP_IN_MEMORY)
128 root 1.69 return;
129    
130 root 1.20 if (out_of_map (newmap, x, y))
131     {
132 root 1.62 LOG (llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", &newmap->path, x, y);
133 root 1.58 x = newmap->enter_x;
134     y = newmap->enter_y;
135 root 1.20 if (out_of_map (newmap, x, y))
136     {
137     LOG (llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n",
138 root 1.62 &newmap->path, x, y, newmap->width, newmap->height);
139     new_draw_info (NDI_UNIQUE, 0, this, "The exit is closed");
140 root 1.20 return;
141     }
142     }
143 root 1.31
144 root 1.78 if (contr && map != newmap && map)
145 root 1.65 if (INVOKE_MAP (LEAVE, map, ARG_PLAYER (contr)))
146     return;
147    
148 root 1.82 // remove, so stupid ob_locked does not trigger a failure
149 root 1.65 remove ();
150    
151 root 1.20 /* try to find a spot for the player */
152 root 1.62 if (ob_blocked (this, newmap, x, y))
153 root 1.20 { /* First choice blocked */
154     /* We try to find a spot for the player, starting closest in.
155     * We could use find_first_free_spot, but that doesn't randomize it at all,
156     * So for example, if the north space is free, you would always end up there even
157     * if other spaces around are available.
158     * Note that for the second and third calls, we could start at a position other
159     * than one, but then we could end up on the other side of walls and so forth.
160     */
161 root 1.62 int i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE1 + 1);
162 root 1.23
163 root 1.20 if (i == -1)
164     {
165 root 1.62 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE2 + 1);
166 root 1.20 if (i == -1)
167 root 1.62 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE);
168 root 1.20 }
169 root 1.31
170 root 1.20 if (i != -1)
171     {
172     x += freearr_x[i];
173     y += freearr_y[i];
174     }
175     else
176 root 1.62 /* not much we can do in this case. */
177     LOG (llevInfo, "enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", &newmap->path, x, y);
178     }
179 elmex 1.1
180 root 1.78 if (contr && map != newmap)
181 root 1.69 {
182     if (INVOKE_PLAYER (MAP_CHANGE, contr, ARG_MAP (newmap), ARG_INT (x), ARG_INT (y)))
183     return;
184 root 1.31
185 root 1.69 if (INVOKE_MAP (ENTER, newmap, ARG_PLAYER (contr), ARG_INT (x), ARG_INT (y)))
186     return;
187     }
188 root 1.20
189 root 1.62 this->x = x;
190     this->y = y;
191     map = newmap;
192 root 1.20
193 root 1.62 insert_ob_in_map (this, map, 0, INS_NO_WALK_ON);
194 root 1.20
195 root 1.82 enemy = 0;
196 root 1.20
197 root 1.62 if (contr)
198 root 1.20 {
199 root 1.70 contr->maplevel = newmap->path;
200 root 1.62 contr->count = 0;
201 root 1.20 }
202    
203     /* Update any golems */
204 root 1.99 if (type == PLAYER)
205 root 1.100 if (object *golem = contr->golem)
206 root 1.99 {
207     int i = find_free_spot (golem, newmap, x, y, 1, SIZEOFFREE);
208    
209     if (i < 0)
210     golem->destroy ();
211     else
212     {
213     newmap->insert (golem, x + freearr_x[i], y + freearr_y[i]);
214     golem->direction = find_dir_2 (x - golem->x, y - golem->y);
215     }
216     }
217 root 1.31
218 root 1.20 /* since the players map is already loaded, we don't need to worry
219     * about pending objects.
220     */
221     remove_all_pets (newmap);
222 elmex 1.1 }
223    
224     /* process_players1 and process_players2 do all the player related stuff.
225     * I moved it out of process events and process_map. This was to some
226     * extent for debugging as well as to get a better idea of the time used
227     * by the various functions. process_players1() does the processing before
228     * objects have been updated, process_players2() does the processing that
229     * is needed after the players have been updated.
230     */
231 root 1.46 static void
232     process_players1 ()
233 elmex 1.1 {
234 root 1.20 /* Basically, we keep looping until all the players have done their actions. */
235 root 1.94 for (int flag = 1; flag != 0;)
236 root 1.20 {
237     flag = 0;
238 root 1.56 for_all_players (pl)
239 root 1.20 {
240 root 1.56 pl->refcnt_chk ();
241 elmex 1.1
242 root 1.109 if (expect_false (!pl->ob || !pl->ns || !pl->ob->active))
243 root 1.20 continue;
244    
245 root 1.106 if (handle_newcs_player (pl->ob))
246     flag = 1;
247     }
248     }
249 root 1.46
250 root 1.55 for_all_players (pl)
251 root 1.20 {
252 root 1.102 object *ob = pl->ob;
253    
254 root 1.109 if (expect_false (!ob || !pl->ns || !ob->active))
255 root 1.56 continue;
256    
257 root 1.102 do_some_living (ob);
258 elmex 1.1 }
259     }
260    
261 root 1.46 static void
262     process_players2 ()
263 elmex 1.1 {
264 root 1.20 /* Then check if any players should use weapon-speed instead of speed */
265 root 1.55 for_all_players (pl)
266 root 1.20 {
267 root 1.106 pl->weapon_sp_left = min (pl->weapon_sp, pl->weapon_sp_left + pl->weapon_sp);
268     pl->ob->speed_left = min (pl->ob->speed, pl->ob->speed_left + pl->ob->speed);
269 elmex 1.1 }
270     }
271    
272 root 1.20 void
273 root 1.46 process_events ()
274 root 1.20 {
275 root 1.46 process_players1 ();
276 elmex 1.1
277 root 1.81 for_all_actives (op)
278 root 1.20 {
279     /* Now process op */
280 root 1.109 if (expect_false (QUERY_FLAG (op, FLAG_FREED)))
281 root 1.20 {
282     LOG (llevError, "BUG: process_events(): Free object on list\n");
283 root 1.59 op->set_speed (0);
284 root 1.20 continue;
285     }
286    
287 root 1.109 if (expect_false (!op->has_active_speed ()))
288 root 1.20 {
289 elmex 1.66 LOG (llevError, "BUG: process_events(): Object %s has no speed (%f), "
290     "but is on active list\n", op->debug_desc (), op->speed);
291 root 1.59 op->set_speed (0);
292 root 1.20 continue;
293 root 1.14 }
294    
295 root 1.109 if (expect_false (op->flag [FLAG_REMOVED]))
296 root 1.20 {
297 root 1.96 LOG (llevError, "BUG: process_events(): removed object is on active list: %s\n",
298     op->debug_desc ());
299 root 1.59 op->set_speed (0);
300 root 1.20 continue;
301 root 1.14 }
302    
303 root 1.46 /* Animate the object. Bug or feature that anim_speed
304 root 1.20 * is based on ticks, and not the creatures speed?
305     */
306     if (op->anim_speed && op->last_anim >= op->anim_speed)
307     {
308 root 1.102 animate_object (op, op->contr ? op->facing : op->direction);
309 root 1.20 op->last_anim = 1;
310     }
311     else
312 root 1.102 ++op->last_anim;
313 elmex 1.1
314 root 1.102 if (op->speed_left > 0.f)
315 root 1.20 {
316     --op->speed_left;
317     process_object (op);
318 root 1.28
319     if (op->destroyed ())
320 root 1.20 continue;
321 root 1.14 }
322 root 1.28
323 root 1.102 if (!op->contr)
324     op->speed_left = min (abs (op->speed), op->speed_left + abs (op->speed));
325 elmex 1.1 }
326    
327 root 1.46 process_players2 ();
328 elmex 1.1 }
329    
330 root 1.62 /* clean up everything before exiting */
331 root 1.20 void
332 root 1.62 emergency_save ()
333 root 1.20 {
334 root 1.62 LOG (llevDebug, "emergency save begin.\n");
335 elmex 1.1
336 root 1.83 cfperl_emergency_save ();
337 root 1.62
338     LOG (llevDebug, "saving book archive.\n");
339     write_book_archive ();
340 root 1.47
341 root 1.62 LOG (llevDebug, "emergency save done.\n");
342 elmex 1.1 }
343    
344 root 1.79 // send all clients some informational text
345     static void
346     cleanup_inform (const char *cause, bool make_core)
347     {
348 root 1.83 int flags = NDI_UNIQUE | NDI_ALL | (make_core ? NDI_RED : NDI_GREEN);
349    
350 root 1.111 new_draw_info_format (flags, 0, 0, "The server will now shutdown.");
351     new_draw_info_format (flags, 0, 0, "Cause for this shutdown: %s", cause);
352 root 1.79
353     if (make_core)
354 root 1.111 new_draw_info_format (flags, 0, 0, "This is considered a crash, but all maps and players have been saved.");
355 root 1.79 else
356 root 1.111 new_draw_info_format (flags, 0, 0, "This is considered to be a clean shutdown, and all maps and players will be saved now.");
357 root 1.79
358 root 1.111 new_draw_info_format (flags, 0, 0, "%s", CLEANUP_MESSAGE);
359 root 1.79
360     flush_sockets ();
361     }
362    
363 elmex 1.1 /* clean up everything before exiting */
364 root 1.20 void
365 root 1.79 cleanup (const char *cause, bool make_core)
366 elmex 1.1 {
367 root 1.84 if (make_core)
368 root 1.85 fork_abort (cause);
369 root 1.84
370 root 1.79 LOG (llevError, "cleanup cause: %s\n", cause);
371    
372     if (!make_core)
373     cleanup_inform (cause, make_core);
374    
375 root 1.62 LOG (llevDebug, "cleanup begin.\n");
376    
377 root 1.65 if (init_done && !in_cleanup)
378 root 1.67 {
379     in_cleanup = true;
380     emergency_save ();
381     }
382     else
383     in_cleanup = true;
384 root 1.29
385 root 1.62 LOG (llevDebug, "running cleanup handlers.\n");
386     INVOKE_GLOBAL (CLEANUP);
387 root 1.23
388 root 1.62 LOG (llevDebug, "cleanup done.\n");
389 root 1.25
390 root 1.49 if (make_core)
391 root 1.79 {
392     cleanup_inform (cause, make_core);
393 root 1.91 cfperl_cleanup (make_core);
394 root 1.84 _exit (1);
395 root 1.79 }
396 root 1.49 else
397 root 1.88 {
398 root 1.111 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_GREEN, 0, 0, "Maps and players successfully saved, exiting.");
399     new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_GREEN, 0, 0, "And again: " CLEANUP_MESSAGE);
400 root 1.88 flush_sockets ();
401 root 1.91 cfperl_cleanup (make_core);
402 root 1.88 _exit (0);
403     }
404 elmex 1.1 }
405    
406 root 1.20 int
407     forbid_play (void)
408 elmex 1.1 {
409     #if !defined(_IBMR2) && !defined(___IBMR2) && defined(PERM_FILE)
410 root 1.20 char buf[MAX_BUF], day[MAX_BUF];
411     FILE *fp;
412     time_t clock;
413     struct tm *tm;
414     int i, start, stop, forbit = 0, comp;
415    
416     clock = time (NULL);
417     tm = (struct tm *) localtime (&clock);
418 root 1.14
419 root 1.20 sprintf (buf, "%s/%s", settings.confdir, PERM_FILE);
420     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
421     return 0;
422    
423     while (fgets (buf, MAX_BUF, fp))
424     {
425     if (buf[0] == '#')
426     continue;
427 root 1.73
428 root 1.20 if (!strncmp (buf, "msg", 3))
429     {
430     if (forbit)
431     while (fgets (buf, MAX_BUF, fp)) /* print message */
432     fputs (buf, logfile);
433     break;
434     }
435     else if (sscanf (buf, "%s %d%*c%d\n", day, &start, &stop) != 3)
436     {
437     LOG (llevDebug, "Warning: Incomplete line in permission file ignored.\n");
438     continue;
439 root 1.14 }
440    
441 root 1.20 for (i = 0; i < 7; i++)
442     {
443     if (!strncmp (buf, days[i], 3) && (tm->tm_wday == i) && (tm->tm_hour >= start) && (tm->tm_hour < stop))
444     forbit = 1;
445 root 1.14 }
446 elmex 1.1 }
447    
448 root 1.20 close_and_delete (fp, comp);
449 elmex 1.1
450 root 1.20 return forbit;
451 elmex 1.1 #else
452 root 1.20 return 0;
453 elmex 1.1 #endif
454     }
455    
456     /*
457 root 1.73 * do_specials() is a collection of functions to call from time to time.
458 elmex 1.1 * Modified 2000-1-14 MSW to use the global pticks count to determine how
459     * often to do things. This will allow us to spred them out more often.
460     * I use prime numbers for the factor count - in that way, it is less likely
461     * these actions will fall on the same tick (compared to say using 500/2500/15000
462     * which would mean on that 15,000 tick count a whole bunch of stuff gets
463     * done). Of course, there can still be times where multiple specials are
464     * done on the same tick, but that will happen very infrequently
465     *
466     * I also think this code makes it easier to see how often we really are
467     * doing the various things.
468     */
469 root 1.20 void
470     do_specials (void)
471     {
472 root 1.109 if (expect_false (!(pticks % TICKS_PER_HOUR)))
473 root 1.95 adjust_daylight ();
474 elmex 1.1
475 root 1.109 if (expect_false (!(pticks % 7)))
476 root 1.20 shstr::gc ();
477 root 1.18
478 root 1.109 if (expect_false (!(pticks % 2503)))
479 root 1.20 fix_weight (); /* Hack to fix weightproblems caused by bugs */
480 elmex 1.1
481 root 1.109 if (expect_false (!(pticks % 5003)))
482 root 1.20 write_book_archive ();
483 elmex 1.1
484 root 1.109 if (expect_false (!(pticks % 5009)))
485 root 1.20 clean_friendly_list ();
486 elmex 1.1
487 root 1.109 if (expect_false (!(pticks % 5011)))
488 root 1.20 obsolete_parties ();
489 elmex 1.1
490 root 1.109 if (expect_false (!(pticks % 12503)))
491 root 1.20 fix_luck ();
492 elmex 1.1 }
493    
494 root 1.20 void
495     server_tick ()
496 root 1.2 {
497 root 1.44 // first do the user visible stuff
498 root 1.20 doeric_server ();
499 root 1.12 INVOKE_GLOBAL (CLOCK);
500 root 1.46 process_events (); /* "do" something with objects with speed */
501 root 1.20 flush_sockets ();
502 root 1.44
503     // then do some bookkeeping, should not really be here
504 root 1.20 do_specials (); /* Routines called from time to time. */
505 root 1.56 attachable::check_mortals ();
506 root 1.5
507     ++pticks;
508 root 1.2 }
509    
510 root 1.87 #if 0
511     // used fro benchmarking (x86/amd64-specific)
512     typedef unsigned long tval;
513     typedef unsigned long long stamp64;
514    
515     extern inline tval
516     stamp (void)
517     {
518     tval tsc;
519     asm volatile ("rdtsc":"=a" (tsc)::"edx");
520    
521     return tsc;
522     }
523    
524     extern inline tval
525     measure (tval t)
526     {
527     tval tsc;
528     asm volatile ("rdtsc":"=a" (tsc)::"edx");
529    
530     if (tsc > t)
531     return tsc - t;
532     else
533     return t - tsc;
534     }
535    
536     int
537     main (int argc, char **argv)
538     {
539     rand_gen rg(0);
540     tval fastest = 0x7fffffff;
541     for (int loop = 10000; loop--; )
542     {
543     tval s = stamp ();
544     volatile int i = rg.get_int(25);
545     fastest = min (fastest, measure (s));
546     }
547    
548     //printf ("fastest %d\n", fastest);
549     for (int i = 0; i < 1024*1024*3; ++i)
550     {
551     char c = rg.get_int (256);
552     write (2, &c, 1);
553     }
554     }
555    
556     #else
557    
558     // normal main
559 root 1.20 int
560     main (int argc, char **argv)
561 elmex 1.1 {
562 root 1.6 settings.argc = argc;
563     settings.argv = argv;
564    
565     init (argc, argv);
566    
567 root 1.10 initPlugins ();
568 elmex 1.1
569 root 1.6 for (;;)
570     cfperl_main ();
571 root 1.64 }
572 root 1.87 #endif
573 root 1.4