ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/main.C
(Generate patch)

Comparing deliantra/server/server/main.C (file contents):
Revision 1.23 by root, Sun Sep 10 15:59:57 2006 UTC vs.
Revision 1.79 by root, Fri Jan 5 10:50:47 2007 UTC

1
2/*
3 * static char *rcsid_main_c =
4 * "$Id: main.C,v 1.23 2006/09/10 15:59:57 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2001-2003 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2001-2003 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
28*/ 22*/
29 23
30#include <global.h> 24#include <global.h>
31#include <object.h> 25#include <object.h>
32#include <tod.h> 26#include <tod.h>
37# ifdef HAVE_CRYPT_H 31# ifdef HAVE_CRYPT_H
38# include <crypt.h> 32# include <crypt.h>
39# endif 33# endif
40#endif 34#endif
41 35
42#ifndef __CEXTRACT__
43# include <sproto.h> 36#include <sproto.h>
44#endif
45
46#ifdef HAVE_TIME_H
47# include <time.h> 37#include <time.h>
48#endif
49 38
50#include <../random_maps/random_map.h> 39#include <../random_maps/random_map.h>
51#include <../random_maps/rproto.h> 40#include <../random_maps/rproto.h>
52#include "path.h" 41#include "path.h"
53 42
56}; 45};
57 46
58void 47void
59version (object *op) 48version (object *op)
60{ 49{
61 if (op != NULL) 50 if (op)
62 clear_win_info (op); 51 clear_win_info (op);
63 52
64 new_draw_info_format (NDI_UNIQUE, 0, op, "This is Crossfire v%s", VERSION); 53 new_draw_info_format (NDI_UNIQUE, 0, op, "This is Crossfire+ v%s", VERSION);
65 54
66/* If in a socket, don't print out the list of authors. It confuses the
67 * crossclient program.
68 */
69 if (op == NULL)
70 return;
71 new_draw_info (NDI_UNIQUE, 0, op, "Authors and contributors to this program:"); 55 new_draw_info (NDI_UNIQUE, 0, op, "Authors and contributors to this program:");
56 new_draw_info (NDI_UNIQUE, 0, op, "Marc A. Lehmann <pcg@goof.com>");
57 new_draw_info (NDI_UNIQUE, 0, op, "Robin Redeker <elmex@x-paste.de>");
58 new_draw_info (NDI_UNIQUE, 0, op, "Pippijn van Steenhoven <pip88nl@gmail.com>");
72 new_draw_info (NDI_UNIQUE, 0, op, "mwedel@sonic.net (Mark Wedel)"); 59 new_draw_info (NDI_UNIQUE, 0, op, "Mark Wedel <mwedel@sonic.net>");
73 new_draw_info (NDI_UNIQUE, 0, op, "frankj@ifi.uio.no (Frank Tore Johansen)"); 60 new_draw_info (NDI_UNIQUE, 0, op, "Frank Tore Johansen <frankj@ifi.uio.no>");
74 new_draw_info (NDI_UNIQUE, 0, op, "kjetilho@ifi.uio.no (Kjetil Torgrim Homme)"); 61 new_draw_info (NDI_UNIQUE, 0, op, "Kjetil Torgrim Homme <kjetilho@ifi.uio.no>");
75 new_draw_info (NDI_UNIQUE, 0, op, "tvangod@ecst.csuchico.edu (Tyler Van Gorder)"); 62 new_draw_info (NDI_UNIQUE, 0, op, "Tyler Van Gorder <tvangod@ecst.csuchico.edu>");
76 new_draw_info (NDI_UNIQUE, 0, op, "elmroth@cd.chalmers.se (Tony Elmroth)"); 63 new_draw_info (NDI_UNIQUE, 0, op, "Tony Elmroth <elmroth@cd.chalmers.se>");
77 new_draw_info (NDI_UNIQUE, 0, op, "dougal.scott@fcit.monasu.edu.au (Dougal Scott)"); 64 new_draw_info (NDI_UNIQUE, 0, op, "Dougal Scott <dougal.scott@fcit.monasu.edu.au>");
78 new_draw_info (NDI_UNIQUE, 0, op, "wchuang@athena.mit.edu (William)"); 65 new_draw_info (NDI_UNIQUE, 0, op, "William <wchuang@athena.mit.edu>");
79 new_draw_info (NDI_UNIQUE, 0, op, "ftww@cs.su.oz.au (Geoff Bailey)"); 66 new_draw_info (NDI_UNIQUE, 0, op, "Geoff Bailey <ftww@cs.su.oz.au>");
80 new_draw_info (NDI_UNIQUE, 0, op, "jorgens@flipper.pvv.unit.no (Kjetil Wiekhorst Jxrgensen)"); 67 new_draw_info (NDI_UNIQUE, 0, op, "Kjetil Wiekhorst Jørgensen <jorgens@flipper.pvv.unit.no>");
81 new_draw_info (NDI_UNIQUE, 0, op, "c.blackwood@rdt.monash.edu.au (Cameron Blackwood)"); 68 new_draw_info (NDI_UNIQUE, 0, op, "Cameron Blackwood <c.blackwood@rdt.monash.edu.au>");
82 new_draw_info (NDI_UNIQUE, 0, op, "jtraub+@cmu.edu (Joseph L. Traub)"); 69 new_draw_info (NDI_UNIQUE, 0, op, "Joseph L. Traub <jtraub+@cmu.edu>");
83 new_draw_info (NDI_UNIQUE, 0, op, "rgg@aaii.oz.au (Rupert G. Goldie)"); 70 new_draw_info (NDI_UNIQUE, 0, op, "Rupert G. Goldie <rgg@aaii.oz.au>");
84 new_draw_info (NDI_UNIQUE, 0, op, "eanders+@cmu.edu (Eric A. Anderson)"); 71 new_draw_info (NDI_UNIQUE, 0, op, "Eric A. Anderson <eanders+@cmu.edu>");
85 new_draw_info (NDI_UNIQUE, 0, op, "eneq@Prag.DoCS.UU.SE (Rickard Eneqvist)"); 72 new_draw_info (NDI_UNIQUE, 0, op, "Rickard Eneqvist <eneq@Prag.DoCS.UU.SE>");
86 new_draw_info (NDI_UNIQUE, 0, op, "Jarkko.Sonninen@lut.fi (Jarkko Sonninen)"); 73 new_draw_info (NDI_UNIQUE, 0, op, "Jarkko Sonninen <Jarkko.Sonninen@lut.fi>");
87 new_draw_info (NDI_UNIQUE, 0, op, "kholland@sunlab.cit.cornell.du (Karl Holland)"); 74 new_draw_info (NDI_UNIQUE, 0, op, "Karl Holland <kholland@sunlab.cit.cornell.du>");
88 new_draw_info (NDI_UNIQUE, 0, op, "vick@bern.docs.uu.se (Mikael Lundgren)"); 75 new_draw_info (NDI_UNIQUE, 0, op, "Mikael Lundgren <vick@bern.docs.uu.se>");
89 new_draw_info (NDI_UNIQUE, 0, op, "mol@meryl.csd.uu.se (Mikael Olsson)"); 76 new_draw_info (NDI_UNIQUE, 0, op, "Mikael Olsson <mol@meryl.csd.uu.se>");
90 new_draw_info (NDI_UNIQUE, 0, op, "Tero.Haatanen@lut.fi (Tero Haatanen)"); 77 new_draw_info (NDI_UNIQUE, 0, op, "Tero Haatanen <Tero.Haatanen@lut.fi>");
91 new_draw_info (NDI_UNIQUE, 0, op, "ylitalo@student.docs.uu.se (Lasse Ylitalo)"); 78 new_draw_info (NDI_UNIQUE, 0, op, "Lasse Ylitalo <ylitalo@student.docs.uu.se>");
92 new_draw_info (NDI_UNIQUE, 0, op, "anipa@guru.magic.fi (Niilo Neuvo)"); 79 new_draw_info (NDI_UNIQUE, 0, op, "Niilo Neuvo <anipa@guru.magic.fi>");
93 new_draw_info (NDI_UNIQUE, 0, op, "mta@modeemi.cs.tut.fi (Markku J{rvinen)"); 80 new_draw_info (NDI_UNIQUE, 0, op, "Markku J{rvinen <mta@modeemi.cs.tut.fi>");
94 new_draw_info (NDI_UNIQUE, 0, op, "meunier@inf.enst.fr (Sylvain Meunier)"); 81 new_draw_info (NDI_UNIQUE, 0, op, "Sylvain Meunier <meunier@inf.enst.fr>");
95 new_draw_info (NDI_UNIQUE, 0, op, "jfosback@darmok.uoregon.edu (Jason Fosback)"); 82 new_draw_info (NDI_UNIQUE, 0, op, "Jason Fosback <jfosback@darmok.uoregon.edu>");
96 new_draw_info (NDI_UNIQUE, 0, op, "cedman@capitalist.princeton.edu (Carl Edman)"); 83 new_draw_info (NDI_UNIQUE, 0, op, "Carl Edman <cedman@capitalist.princeton.edu>");
97 new_draw_info (NDI_UNIQUE, 0, op, "henrich@crh.cl.msu.edu (Charles Henrich)"); 84 new_draw_info (NDI_UNIQUE, 0, op, "Charles Henrich <henrich@crh.cl.msu.edu>");
98 new_draw_info (NDI_UNIQUE, 0, op, "schmid@fb3-s7.math.tu-berlin.de (Gregor Schmid)"); 85 new_draw_info (NDI_UNIQUE, 0, op, "Gregor Schmid <schmid@fb3-s7.math.tu-berlin.de>");
99 new_draw_info (NDI_UNIQUE, 0, op, "quinet@montefiore.ulg.ac.be (Raphael Quinet)"); 86 new_draw_info (NDI_UNIQUE, 0, op, "Raphael Quinet <quinet@montefiore.ulg.ac.be>");
100 new_draw_info (NDI_UNIQUE, 0, op, "jam@modeemi.cs.tut.fi (Jari Vanhala)"); 87 new_draw_info (NDI_UNIQUE, 0, op, "Jari Vanhala <jam@modeemi.cs.tut.fi>");
101 new_draw_info (NDI_UNIQUE, 0, op, "kivinen@joker.cs.hut.fi (Tero Kivinen)"); 88 new_draw_info (NDI_UNIQUE, 0, op, "Tero Kivinen <kivinen@joker.cs.hut.fi>");
102 new_draw_info (NDI_UNIQUE, 0, op, "peterm@soda.berkeley.edu (Peter Mardahl)"); 89 new_draw_info (NDI_UNIQUE, 0, op, "Peter Mardahl <peterm@soda.berkeley.edu>");
103 new_draw_info (NDI_UNIQUE, 0, op, "matt@cs.odu.edu (Matthew Zeher)"); 90 new_draw_info (NDI_UNIQUE, 0, op, "Matthew Zeher <matt@cs.odu.edu>");
104 new_draw_info (NDI_UNIQUE, 0, op, "srt@sun-dimas.aero.org (Scott R. Turner)"); 91 new_draw_info (NDI_UNIQUE, 0, op, "Scott R. Turner <srt@sun-dimas.aero.org>");
105 new_draw_info (NDI_UNIQUE, 0, op, "huma@netcom.com (Ben Fennema)"); 92 new_draw_info (NDI_UNIQUE, 0, op, "Ben Fennema <huma@netcom.com>");
106 new_draw_info (NDI_UNIQUE, 0, op, "njw@cs.city.ac.uk (Nick Williams)"); 93 new_draw_info (NDI_UNIQUE, 0, op, "Nick Williams <njw@cs.city.ac.uk>");
107 new_draw_info (NDI_UNIQUE, 0, op, "Wacren@Gin.ObsPM.Fr (Laurent Wacrenier)"); 94 new_draw_info (NDI_UNIQUE, 0, op, "Laurent Wacrenier <Wacren@Gin.ObsPM.Fr>");
108 new_draw_info (NDI_UNIQUE, 0, op, "thomas@astro.psu.edu (Brian Thomas)"); 95 new_draw_info (NDI_UNIQUE, 0, op, "Brian Thomas <thomas@astro.psu.edu>");
109 new_draw_info (NDI_UNIQUE, 0, op, "jsm@axon.ksc.nasa.gov (John Steven Moerk)"); 96 new_draw_info (NDI_UNIQUE, 0, op, "John Steven Moerk <jsm@axon.ksc.nasa.gov>");
110 new_draw_info (NDI_UNIQUE, 0, op, "Delbecq David [david.delbecq@mailandnews.com]"); 97 new_draw_info (NDI_UNIQUE, 0, op, "Delbecq David <david.delbecq@mailandnews.com>");
111 new_draw_info (NDI_UNIQUE, 0, op, "Chachkoff Yann [yann.chachkoff@mailandnews.com]\n"); 98 new_draw_info (NDI_UNIQUE, 0, op, "Chachkoff Yann <yann.chachkoff@mailandnews.com>\n");
99
112 new_draw_info (NDI_UNIQUE, 0, op, "Images and art:"); 100 new_draw_info (NDI_UNIQUE, 0, op, "Images and art:");
113 new_draw_info (NDI_UNIQUE, 0, op, "Peter Gardner"); 101 new_draw_info (NDI_UNIQUE, 0, op, "Peter Gardner");
114 new_draw_info (NDI_UNIQUE, 0, op, "David Gervais [david_eg@mail.com]"); 102 new_draw_info (NDI_UNIQUE, 0, op, "David Gervais <david_eg@mail.com>");
115 new_draw_info (NDI_UNIQUE, 0, op, "Mitsuhiro Itakura [ita@gold.koma.jaeri.go.jp]"); 103 new_draw_info (NDI_UNIQUE, 0, op, "Mitsuhiro Itakura <ita@gold.koma.jaeri.go.jp>");
116 new_draw_info (NDI_UNIQUE, 0, op, "Hansjoerg Malthaner [hansjoerg.malthaner@danet.de]"); 104 new_draw_info (NDI_UNIQUE, 0, op, "Hansjoerg Malthaner <hansjoerg.malthaner@danet.de>");
117 new_draw_info (NDI_UNIQUE, 0, op, "Mårten Woxberg [maxmc@telia.com]"); 105 new_draw_info (NDI_UNIQUE, 0, op, "MÃ¥rten Woxberg <maxmc@telia.com>");
118 new_draw_info (NDI_UNIQUE, 0, op, "And many more!"); 106 new_draw_info (NDI_UNIQUE, 0, op, "And many more!");
119}
120
121void
122info_keys (object *op)
123{
124 clear_win_info (op);
125 new_draw_info (NDI_UNIQUE, 0, op, "Push `hjklynub' to walk in a direction.");
126 new_draw_info (NDI_UNIQUE, 0, op, "Shift + dir = fire, Ctrl + dir = run");
127 new_draw_info (NDI_UNIQUE, 0, op, "(To fire at yourself, hit `.'");
128 new_draw_info (NDI_UNIQUE, 0, op, "To attack, walk into the monsters.");
129 new_draw_info (NDI_UNIQUE, 0, op, "\" = speak ' = extended command");
130 new_draw_info (NDI_UNIQUE, 0, op, "i = inventory , = get : = look");
131 new_draw_info (NDI_UNIQUE, 0, op, "<> = rotate d = drop ? = help");
132 new_draw_info (NDI_UNIQUE, 0, op, "a = apply A = apply below t = throw");
133 new_draw_info (NDI_UNIQUE, 0, op, "e = examine E = exa below @ = autopick");
134 new_draw_info (NDI_UNIQUE, 0, op, "C = configure s = brace v = version");
135 new_draw_info (NDI_UNIQUE, 0, op, "+- = change range <tab> = browse spells");
136 new_draw_info (NDI_UNIQUE, 0, op, "x = change inventory type");
137 new_draw_info (NDI_UNIQUE, 0, op, "Mouse: L = examine, M = apply, R = drop/get");
138 new_draw_info (NDI_UNIQUE, 0, op, "'help = info about extended commands.");
139 new_draw_info (NDI_UNIQUE, 0, op, "Ctrl-R = refresh Ctrl-C = clear");
140 new_draw_info (NDI_UNIQUE, 0, op, "You can type a number before most commands.");
141 new_draw_info (NDI_UNIQUE, 0, op, "(For instance 3d drops 3 items.)");
142}
143
144void
145start_info (object *op)
146{
147 char buf[MAX_BUF];
148
149 sprintf (buf, "Welcome to Crossfire, v%s!", VERSION);
150 new_draw_info (NDI_UNIQUE, 0, op, buf);
151 new_draw_info (NDI_UNIQUE, 0, op, "Press `?' for help");
152 new_draw_info (NDI_UNIQUE, 0, op, " ");
153 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, op, "%s entered the game.", &op->name);
154 if (!op->contr->name_changed)
155 {
156 new_draw_info (NDI_UNIQUE, 0, op, "Note that you must set your name with the name");
157 new_draw_info (NDI_UNIQUE, 0, op, "command to enter the highscore list.");
158 new_draw_info (NDI_UNIQUE, 0, op, "(You can also use the crossfire.name X-resource.)");
159 }
160}
161
162/* Really, there is no reason to crypt the passwords any system. But easier
163 * to just leave this enabled for backward compatibility. Put the
164 * simple case at top - no encryption - makes it easier to read.
165 */
166char *
167crypt_string (char *str, char *salt)
168{
169#if defined(WIN32) || (defined(__FreeBSD__) && !defined(HAVE_LIBDES))
170 return (str);
171#else
172 static char *c = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
173 char s[2];
174
175 if (salt == NULL)
176 s[0] = c[RANDOM () % (int) strlen (c)], s[1] = c[RANDOM () % (int) strlen (c)];
177 else
178 s[0] = salt[0], s[1] = salt[1];
179
180# ifdef HAVE_LIBDES
181 return (char *) des_crypt (str, s);
182# endif
183 /* Default case - just use crypt */
184 return (char *) crypt (str, s);
185#endif
186}
187
188int
189check_password (char *typed, char *crypted)
190{
191 return !strcmp (crypt_string (typed, crypted), crypted);
192} 107}
193 108
194/* This is a basic little function to put the player back to his 109/* This is a basic little function to put the player back to his
195 * savebed. We do some error checking - its possible that the 110 * savebed. We do some error checking - its possible that the
196 * savebed map may no longer exist, so we make sure the player 111 * savebed map may no longer exist, so we make sure the player
197 * goes someplace. 112 * goes someplace.
198 */ 113 */
199void 114void
200enter_player_savebed (object *op) 115enter_player_savebed (object *op)
201{ 116{
202 mapstruct *oldmap = op->map; 117 object *tmp = object::create ();
203 object *tmp;
204
205 tmp = get_object ();
206
207 EXIT_PATH (tmp) = op->contr->savebed_map; 118 EXIT_PATH (tmp) = op->contr->savebed_map;
208 EXIT_X (tmp) = op->contr->bed_x; 119 EXIT_X (tmp) = op->contr->bed_x;
209 EXIT_Y (tmp) = op->contr->bed_y; 120 EXIT_Y (tmp) = op->contr->bed_y;
210 enter_exit (op, tmp); 121 op->enter_exit (tmp);
211 /* If the player has not changed maps and the name does not match 122 tmp->destroy ();
212 * that of the savebed, his savebed map is gone. Lets go back
213 * to the emergency path. Update what the players savebed is
214 * while we're at it.
215 */
216 if (oldmap == op->map && strcmp (op->contr->savebed_map, oldmap->path))
217 {
218 LOG (llevDebug, "Player %s savebed location %s is invalid - going to emergency location (%s)\n",
219 settings.emergency_mapname, &op->name, op->contr->savebed_map);
220 strcpy (op->contr->savebed_map, settings.emergency_mapname);
221 op->contr->bed_x = settings.emergency_x;
222 op->contr->bed_y = settings.emergency_y;
223 EXIT_PATH (tmp) = op->contr->savebed_map;
224 EXIT_X (tmp) = op->contr->bed_x;
225 EXIT_Y (tmp) = op->contr->bed_y;
226 enter_exit (op, tmp);
227 }
228 free_object (tmp);
229}
230
231/* All this really is is a glorified remove_object that also updates
232 * the counts on the map if needed.
233 */
234void
235leave_map (object *op)
236{
237 mapstruct *oldmap = op->map;
238
239 remove_ob (op);
240
241 if (oldmap)
242 {
243 if (!op->contr->hidden)
244 oldmap->players--;
245 if (oldmap->players <= 0)
246 { /* can be less than zero due to errors in tracking this */
247 set_map_timeout (oldmap);
248 }
249 }
250} 123}
251 124
252/* 125/*
253 * enter_map(): Moves the player and pets from current map (if any) to 126 * enter_map(): Moves the player and pets from current map (if any) to
254 * new map. map, x, y must be set. map is the map we are moving the 127 * new map. map, x, y must be set. map is the map we are moving the
255 * player to - it could be the map he just came from if the load failed for 128 * player to - it could be the map he just came from if the load failed for
256 * whatever reason. If default map coordinates are to be used, then 129 * whatever reason. If default map coordinates are to be used, then
257 * the function that calls this should figure them out. 130 * the function that calls this should figure them out.
258 */ 131 */
259static void 132void
260enter_map (object *op, mapstruct *newmap, int x, int y) 133object::enter_map (maptile *newmap, int x, int y)
261{ 134{
262 mapstruct *oldmap = op->map; 135 if (destroyed () || !newmap || newmap->in_memory != MAP_IN_MEMORY)
136 return;
263 137
264 if (out_of_map (newmap, x, y)) 138 if (out_of_map (newmap, x, y))
265 { 139 {
266 LOG (llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", newmap->path, x, y); 140 LOG (llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", &newmap->path, x, y);
267 x = MAP_ENTER_X (newmap); 141 x = newmap->enter_x;
268 y = MAP_ENTER_Y (newmap); 142 y = newmap->enter_y;
269 if (out_of_map (newmap, x, y)) 143 if (out_of_map (newmap, x, y))
270 { 144 {
271 LOG (llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", 145 LOG (llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n",
272 newmap->path, x, y, MAP_WIDTH (newmap), MAP_HEIGHT (newmap)); 146 &newmap->path, x, y, newmap->width, newmap->height);
273 new_draw_info (NDI_UNIQUE, 0, op, "The exit is closed"); 147 new_draw_info (NDI_UNIQUE, 0, this, "The exit is closed");
274 return; 148 return;
275 } 149 }
276 } 150 }
151
152 if (contr && map != newmap && map)
153 if (INVOKE_MAP (LEAVE, map, ARG_PLAYER (contr)))
154 return;
155
156 /* If it is a player login, he has yet to be inserted anyplace.
157 * otherwise, we need to deal with removing the player here.
158 */
159 remove ();
160
277 /* try to find a spot for the player */ 161 /* try to find a spot for the player */
278 if (ob_blocked (op, newmap, x, y)) 162 if (ob_blocked (this, newmap, x, y))
279 { /* First choice blocked */ 163 { /* First choice blocked */
280 /* We try to find a spot for the player, starting closest in. 164 /* We try to find a spot for the player, starting closest in.
281 * We could use find_first_free_spot, but that doesn't randomize it at all, 165 * We could use find_first_free_spot, but that doesn't randomize it at all,
282 * So for example, if the north space is free, you would always end up there even 166 * So for example, if the north space is free, you would always end up there even
283 * if other spaces around are available. 167 * if other spaces around are available.
284 * Note that for the second and third calls, we could start at a position other 168 * Note that for the second and third calls, we could start at a position other
285 * than one, but then we could end up on the other side of walls and so forth. 169 * than one, but then we could end up on the other side of walls and so forth.
286 */ 170 */
287 int i = find_free_spot (op, newmap, x, y, 1, SIZEOFFREE1 + 1); 171 int i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE1 + 1);
288 172
289 if (i == -1) 173 if (i == -1)
290 { 174 {
291 i = find_free_spot (op, newmap, x, y, 1, SIZEOFFREE2 + 1); 175 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE2 + 1);
292 if (i == -1) 176 if (i == -1)
293 i = find_free_spot (op, newmap, x, y, 1, SIZEOFFREE); 177 i = find_free_spot (this, newmap, x, y, 1, SIZEOFFREE);
294 } 178 }
179
295 if (i != -1) 180 if (i != -1)
296 { 181 {
297 x += freearr_x[i]; 182 x += freearr_x[i];
298 y += freearr_y[i]; 183 y += freearr_y[i];
299 } 184 }
300 else 185 else
301 {
302 /* not much we can do in this case. */ 186 /* not much we can do in this case. */
303 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); 187 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);
304 }
305 } /* end if looking for free spot */
306
307 if (op->map != NULL)
308 { 188 }
309 INVOKE_PLAYER (MAP_CHANGE, op->contr, ARG_MAP (op->map), ARG_MAP (newmap)); 189
310 INVOKE_MAP (LEAVE, op->map, ARG_PLAYER (op->contr)); 190 if (contr && map != newmap)
311 } 191 {
192 if (INVOKE_PLAYER (MAP_CHANGE, contr, ARG_MAP (newmap), ARG_INT (x), ARG_INT (y)))
193 return;
312 194
313 /* If it is a player login, he has yet to be inserted anyplace. 195 if (INVOKE_MAP (ENTER, newmap, ARG_PLAYER (contr), ARG_INT (x), ARG_INT (y)))
314 * otherwise, we need to deal with removing the player here. 196 return;
315 */ 197 }
316 if (!QUERY_FLAG (op, FLAG_REMOVED))
317 remove_ob (op);
318 198
319 /* remove_ob clears these so they must be reset after the remove_ob call */
320 op->x = x; 199 this->x = x;
321 op->y = y; 200 this->y = y;
322 op->map = newmap; 201 map = newmap;
202
323 insert_ob_in_map (op, op->map, NULL, INS_NO_WALK_ON); 203 insert_ob_in_map (this, map, 0, INS_NO_WALK_ON);
324 204
325 INVOKE_MAP (ENTER, op->map, ARG_PLAYER (op->contr));
326
327 if (!op->contr->hidden)
328 newmap->players++;
329
330 newmap->timeout = 0;
331 op->enemy = NULL; 205 enemy = NULL;
332 206
333 if (op->contr) 207 if (contr)
334 { 208 {
335 strcpy (op->contr->maplevel, newmap->path); 209 contr->maplevel = newmap->path;
336 op->contr->count = 0; 210 contr->count = 0;
337 } 211 }
338 212
339 /* Update any golems */ 213 /* Update any golems */
340 if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL) 214 if (type == PLAYER && contr->ranges[range_golem])
341 { 215 {
342 int i = find_free_spot (op->contr->ranges[range_golem], newmap, 216 int i = find_free_spot (contr->ranges[range_golem], newmap,
343 x, y, 1, SIZEOFFREE); 217 x, y, 1, SIZEOFFREE);
344 218
345 remove_ob (op->contr->ranges[range_golem]); 219 contr->ranges[range_golem]->remove ();
220
346 if (i == -1) 221 if (i == -1)
347 { 222 {
348 remove_friendly_object (op->contr->ranges[range_golem]); 223 remove_friendly_object (contr->ranges[range_golem]);
349 free_object (op->contr->ranges[range_golem]); 224 contr->ranges[range_golem]->destroy ();
350 op->contr->ranges[range_golem] = NULL; 225 contr->ranges[range_golem] = 0;
351 op->contr->golem_count = 0;
352 } 226 }
353 else 227 else
354 { 228 {
355 object *tmp;
356
357 for (tmp = op->contr->ranges[range_golem]; tmp != NULL; tmp = tmp->more) 229 for (object *tmp = contr->ranges[range_golem]; tmp != NULL; tmp = tmp->more)
358 { 230 {
359 tmp->x = x + freearr_x[i] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x); 231 tmp->x = x + freearr_x[i] + (tmp->arch ? 0 : tmp->arch->clone.x);
360 tmp->y = y + freearr_y[i] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y); 232 tmp->y = y + freearr_y[i] + (tmp->arch ? 0 : tmp->arch->clone.y);
361 tmp->map = newmap; 233 tmp->map = newmap;
362 } 234 }
235
363 insert_ob_in_map (op->contr->ranges[range_golem], newmap, NULL, 0); 236 insert_ob_in_map (contr->ranges[range_golem], newmap, NULL, 0);
364 op->contr->ranges[range_golem]->direction = 237 contr->ranges[range_golem]->direction =
365 find_dir_2 (op->x - op->contr->ranges[range_golem]->x, op->y - op->contr->ranges[range_golem]->y); 238 find_dir_2 (x - contr->ranges[range_golem]->x, y - contr->ranges[range_golem]->y);
366 } 239 }
367 } 240 }
368 op->direction = 0;
369 241
370 /* since the players map is already loaded, we don't need to worry 242 /* since the players map is already loaded, we don't need to worry
371 * about pending objects. 243 * about pending objects.
372 */ 244 */
373 remove_all_pets (newmap); 245 remove_all_pets (newmap);
374
375 /* If the player is changing maps, we need to do some special things
376 * Do this after the player is on the new map - otherwise the force swap of the
377 * old map does not work.
378 */
379 if (oldmap != newmap)
380 {
381 if (oldmap) /* adjust old map */
382 {
383 oldmap->players--;
384
385 if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */
386 set_map_timeout (oldmap);
387 }
388 }
389} 246}
390
391void
392set_map_timeout (mapstruct *oldmap)
393{
394#if MAP_MAXTIMEOUT
395 oldmap->timeout = MAP_TIMEOUT (oldmap);
396 /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is
397 * lower than the min value.
398 */
399# if MAP_MINTIMEOUT
400 if (oldmap->timeout < MAP_MINTIMEOUT)
401 {
402 oldmap->timeout = MAP_MINTIMEOUT;
403 }
404# endif
405 if (oldmap->timeout > MAP_MAXTIMEOUT)
406 {
407 oldmap->timeout = MAP_MAXTIMEOUT;
408 }
409#else
410 /* save out the map */
411 swap_map (oldmap);
412#endif /* MAP_MAXTIMEOUT */
413}
414
415
416/* clean_path takes a path and replaces all / with _
417 * We do a strcpy so that we do not change the original string.
418 */
419char *
420clean_path (const char *file)
421{
422 static char newpath[MAX_BUF], *cp;
423
424 strncpy (newpath, file, MAX_BUF - 1);
425 newpath[MAX_BUF - 1] = '\0';
426 for (cp = newpath; *cp != '\0'; cp++)
427 {
428 if (*cp == '/')
429 *cp = '_';
430 }
431 return newpath;
432}
433
434
435/* unclean_path takes a path and replaces all _ with /
436 * This basically undoes clean path.
437 * We do a strcpy so that we do not change the original string.
438 * We are smart enough to start after the last / in case we
439 * are getting passed a string that points to a unique map
440 * path.
441 */
442char *
443unclean_path (const char *src)
444{
445 static char newpath[MAX_BUF], *cp;
446
447 cp = strrchr (src, '/');
448 if (cp)
449 strncpy (newpath, cp + 1, MAX_BUF - 1);
450 else
451 strncpy (newpath, src, MAX_BUF - 1);
452 newpath[MAX_BUF - 1] = '\0';
453
454 for (cp = newpath; *cp != '\0'; cp++)
455 {
456 if (*cp == '_')
457 *cp = '/';
458 }
459 return newpath;
460}
461
462
463/* The player is trying to enter a randomly generated map. In this case, generate the
464 * random map as needed.
465 */
466
467static void
468enter_random_map (object *pl, object *exit_ob)
469{
470 mapstruct *new_map;
471 char newmap_name[HUGE_BUF], *cp;
472 static int reference_number = 0;
473 RMParms rp;
474
475 memset (&rp, 0, sizeof (RMParms));
476 rp.Xsize = -1;
477 rp.Ysize = -1;
478 rp.region = get_region_by_map (exit_ob->map);
479 if (exit_ob->msg)
480 set_random_map_variable (&rp, exit_ob->msg);
481 rp.origin_x = exit_ob->x;
482 rp.origin_y = exit_ob->y;
483 strcpy (rp.origin_map, pl->map->path);
484
485 /* If we have a final_map, use it as a base name to give some clue
486 * as where the player is. Otherwise, use the origin map.
487 * Take the last component (after the last slash) to give
488 * shorter names without bogus slashes.
489 */
490 if (rp.final_map[0])
491 {
492 cp = strrchr (rp.final_map, '/');
493 if (!cp)
494 cp = rp.final_map;
495 }
496 else
497 {
498 char buf[HUGE_BUF];
499
500 cp = strrchr (rp.origin_map, '/');
501 if (!cp)
502 cp = rp.origin_map;
503 /* Need to strip of any trailing digits, if it has them */
504 strcpy (buf, cp);
505 while (isdigit (buf[strlen (buf) - 1]))
506 buf[strlen (buf) - 1] = 0;
507 cp = buf;
508 }
509
510 sprintf (newmap_name, "/random/%s%04d", cp + 1, reference_number++);
511
512 /* now to generate the actual map. */
513 new_map = generate_random_map (newmap_name, &rp);
514
515 /* Update the exit_ob so it now points directly at the newly created
516 * random maps. Not that it is likely to happen, but it does mean that a
517 * exit in a unique map leading to a random map will not work properly.
518 * It also means that if the created random map gets reset before
519 * the exit leading to it, that the exit will no longer work.
520 */
521 if (new_map)
522 {
523 int x, y;
524
525 x = EXIT_X (exit_ob) = MAP_ENTER_X (new_map);
526 y = EXIT_Y (exit_ob) = MAP_ENTER_Y (new_map);
527 EXIT_PATH (exit_ob) = newmap_name;
528 strcpy (new_map->path, newmap_name);
529 enter_map (pl, new_map, x, y);
530 }
531}
532
533/* The player is trying to enter a non-randomly generated template map. In this
534 * case, use a map file for a template
535 */
536
537static void
538enter_fixed_template_map (object *pl, object *exit_ob)
539{
540 mapstruct *new_map;
541 char tmpnum[32], exitpath[HUGE_BUF], resultname[HUGE_BUF], tmpstring[HUGE_BUF], *sourcemap;
542 const char *new_map_name;
543
544 /* Split the exit path string into two parts, one
545 * for where to store the map, and one for were
546 * to generate the map from.
547 */
548 snprintf (exitpath, sizeof (exitpath), "%s", EXIT_PATH (exit_ob) + 2);
549 sourcemap = strchr (exitpath, '!');
550 if (!sourcemap)
551 {
552 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is closed.", &exit_ob->name);
553 /* Should only occur when no source map is set.
554 */
555 LOG (llevError, "enter_fixed_template_map: Exit %s (%d,%d) on map %s has no source template.\n",
556 &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
557 return;
558 }
559 *sourcemap++ = '\0';
560
561 /* If we are not coming from a template map, we can use relative directories
562 * for the map to generate from.
563 */
564 if (!exit_ob->map->templatemap)
565 {
566 sourcemap = path_combine_and_normalize (exit_ob->map->path, sourcemap);
567 }
568
569 /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
570 * of the exit, and the name of the map the exit is on, respectively.
571 */
572 sprintf (tmpnum, "%d", exit_ob->x);
573 replace (exitpath, "%x", tmpnum, resultname, sizeof (resultname));
574
575 sprintf (tmpnum, "%d", exit_ob->y);
576 sprintf (tmpstring, "%s", resultname);
577 replace (tmpstring, "%y", tmpnum, resultname, sizeof (resultname));
578
579 sprintf (tmpstring, "%s", resultname);
580 replace (tmpstring, "%n", exit_ob->map->name, resultname, sizeof (resultname));
581
582 /* If we are coming from another template map, use reletive paths unless
583 * indicated otherwise.
584 */
585 if (exit_ob->map->templatemap && (resultname[0] != '/'))
586 {
587 new_map_name = path_combine_and_normalize (exit_ob->map->path, resultname);
588 }
589 else
590 {
591 new_map_name = create_template_pathname (resultname);
592 }
593
594 /* Attempt to load the map, if unable to, then
595 * create the map from the template.
596 */
597 new_map = ready_map_name (new_map_name, MAP_PLAYER_UNIQUE);
598 if (!new_map)
599 {
600 new_map = load_original_map (create_pathname (sourcemap), MAP_PLAYER_UNIQUE);
601 if (new_map)
602 fix_auto_apply (new_map);
603 }
604
605 if (new_map)
606 {
607 /* set the path of the map to where it should be
608 * so we don't just save over the source map.
609 */
610 strcpy (new_map->path, new_map_name);
611 new_map->templatemap = 1;
612 enter_map (pl, new_map, EXIT_X (exit_ob), EXIT_Y (exit_ob));
613 }
614 else
615 {
616 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is closed.", &exit_ob->name);
617 /* Should only occur when an invalid source map is set.
618 */
619 LOG (llevDebug, "enter_fixed_template_map: Exit %s (%d,%d) on map %s leads no where.\n",
620 &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
621 }
622}
623
624
625/* The player is trying to enter a randomly generated template map. In this
626 * case, generate the map as needed.
627 */
628
629static void
630enter_random_template_map (object *pl, object *exit_ob)
631{
632 mapstruct *new_map;
633 char tmpnum[32], resultname[HUGE_BUF], tmpstring[HUGE_BUF];
634 const char *new_map_name;
635 RMParms rp;
636
637 /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
638 * of the exit, and the name of the map the exit is on, respectively.
639 */
640 sprintf (tmpnum, "%d", exit_ob->x);
641 replace (EXIT_PATH (exit_ob) + 3, "%x", tmpnum, resultname, sizeof (resultname));
642
643 sprintf (tmpnum, "%d", exit_ob->y);
644 sprintf (tmpstring, "%s", resultname);
645 replace (tmpstring, "%y", tmpnum, resultname, sizeof (resultname));
646
647 sprintf (tmpstring, "%s", resultname);
648 replace (tmpstring, "%n", exit_ob->map->name, resultname, sizeof (resultname));
649
650 /* If we are coming from another template map, use reletive paths unless
651 * indicated otherwise.
652 */
653 if (exit_ob->map->templatemap && (resultname[0] != '/'))
654 {
655 new_map_name = path_combine_and_normalize (exit_ob->map->path, resultname);
656 }
657 else
658 {
659 new_map_name = create_template_pathname (resultname);
660 }
661
662 new_map = ready_map_name (new_map_name, MAP_PLAYER_UNIQUE);
663 if (!new_map)
664 {
665 memset (&rp, 0, sizeof (RMParms));
666 rp.Xsize = -1;
667 rp.Ysize = -1;
668 rp.region = get_region_by_map (exit_ob->map);
669 if (exit_ob->msg)
670 set_random_map_variable (&rp, exit_ob->msg);
671 rp.origin_x = exit_ob->x;
672 rp.origin_y = exit_ob->y;
673 strcpy (rp.origin_map, pl->map->path);
674
675 /* now to generate the actual map. */
676 new_map = generate_random_map (new_map_name, &rp);
677 }
678
679
680 /* Update the exit_ob so it now points directly at the newly created
681 * random maps. Not that it is likely to happen, but it does mean that a
682 * exit in a unique map leading to a random map will not work properly.
683 * It also means that if the created random map gets reset before
684 * the exit leading to it, that the exit will no longer work.
685 */
686 if (new_map)
687 {
688 int x, y;
689
690 x = EXIT_X (exit_ob) = MAP_ENTER_X (new_map);
691 y = EXIT_Y (exit_ob) = MAP_ENTER_Y (new_map);
692 new_map->templatemap = 1;
693 enter_map (pl, new_map, x, y);
694 }
695}
696
697
698/* Code to enter/detect a character entering a unique map.
699 */
700static void
701enter_unique_map (object *op, object *exit_ob)
702{
703 char apartment[HUGE_BUF];
704 mapstruct *newmap;
705
706 if (EXIT_PATH (exit_ob)[0] == '/')
707 {
708 sprintf (apartment, "%s/%s/%s/%s", settings.localdir, settings.playerdir, &op->name, clean_path (EXIT_PATH (exit_ob)));
709 newmap = ready_map_name (apartment, MAP_PLAYER_UNIQUE);
710 if (!newmap)
711 {
712 newmap = load_original_map (create_pathname (EXIT_PATH (exit_ob)), MAP_PLAYER_UNIQUE);
713 if (newmap)
714 fix_auto_apply (newmap);
715 }
716 }
717 else
718 { /* relative directory */
719 char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp;
720
721 if (exit_ob->map->unique)
722 {
723
724 strcpy (reldir, unclean_path (exit_ob->map->path));
725
726 /* Need to copy this over, as clean_path only has one static return buffer */
727 strcpy (tmpc, clean_path (reldir));
728 /* Remove final component, if any */
729 if ((cp = strrchr (tmpc, '_')) != NULL)
730 *cp = 0;
731
732 sprintf (apartment, "%s/%s/%s/%s_%s", settings.localdir, settings.playerdir, &op->name, tmpc, clean_path (EXIT_PATH (exit_ob)));
733
734 newmap = ready_map_name (apartment, MAP_PLAYER_UNIQUE);
735 if (!newmap)
736 {
737 newmap = load_original_map (create_pathname (path_combine_and_normalize (reldir, EXIT_PATH (exit_ob))), MAP_PLAYER_UNIQUE);
738 if (newmap)
739 fix_auto_apply (newmap);
740 }
741 }
742 else
743 {
744 /* The exit is unique, but the map we are coming from is not unique. So
745 * use the basic logic - don't need to demangle the path name
746 */
747 sprintf (apartment, "%s/%s/%s/%s", settings.localdir,
748 settings.playerdir, &op->name, clean_path (path_combine_and_normalize (exit_ob->map->path, EXIT_PATH (exit_ob))));
749 newmap = ready_map_name (apartment, MAP_PLAYER_UNIQUE);
750 if (!newmap)
751 {
752 newmap = ready_map_name (path_combine_and_normalize (exit_ob->map->path, EXIT_PATH (exit_ob)), 0);
753 if (newmap)
754 fix_auto_apply (newmap);
755 }
756 }
757 }
758
759 if (newmap)
760 {
761 strcpy (newmap->path, apartment);
762 newmap->unique = 1;
763 enter_map (op, newmap, EXIT_X (exit_ob), EXIT_Y (exit_ob));
764 }
765 else
766 {
767 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name);
768 /* Perhaps not critical, but I would think that the unique maps
769 * should be new enough this does not happen. This also creates
770 * a strange situation where some players could perhaps have visited
771 * such a map before it was removed, so they have the private
772 * map, but other players can't get it anymore.
773 */
774 LOG (llevDebug, "enter_unique_map: Exit %s (%d,%d) on map %s is leads no where.\n",
775 &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
776 }
777
778}
779
780
781/* Tries to move 'op' to exit_ob. op is the character or monster that is
782 * using the exit, where exit_ob is the exit object (boat, door, teleporter,
783 * etc.) if exit_ob is null, then op->contr->maplevel contains that map to
784 * move the object to. This is used when loading the player.
785 *
786 * Largely redone by MSW 2001-01-21 - this function was overly complex
787 * and had some obscure bugs.
788 */
789
790void
791enter_exit (object *op, object *exit_ob)
792{
793#define PORTAL_DESTINATION_NAME "Town portal destination" /* this one should really be in a header file */
794 object *tmp;
795
796 /* It may be nice to support other creatures moving across
797 * exits, but right now a lot of the code looks at op->contr,
798 * so thta is an RFE.
799 */
800 if (op->type != PLAYER)
801 return;
802
803 /* First, lets figure out what map the player is going to go to */
804 if (exit_ob)
805 {
806
807 /* check to see if we make a template map */
808 if (EXIT_PATH (exit_ob) && EXIT_PATH (exit_ob)[1] == '@')
809 {
810 if (EXIT_PATH (exit_ob)[2] == '!')
811 {
812 /* generate a template map randomly */
813 enter_random_template_map (op, exit_ob);
814 }
815 else
816 {
817 /* generate a template map from a fixed template */
818 enter_fixed_template_map (op, exit_ob);
819 }
820 }
821 /* check to see if we make a randomly generated map */
822 else if (EXIT_PATH (exit_ob) && EXIT_PATH (exit_ob)[1] == '!')
823 {
824 enter_random_map (op, exit_ob);
825 }
826 else if (QUERY_FLAG (exit_ob, FLAG_UNIQUE))
827 {
828 enter_unique_map (op, exit_ob);
829 }
830 else
831 {
832 int x = EXIT_X (exit_ob), y = EXIT_Y (exit_ob);
833
834 /* 'Normal' exits that do not do anything special
835 * Simple enough we don't need another routine for it.
836 */
837 mapstruct *newmap;
838
839 if (exit_ob->map)
840 {
841 newmap = ready_map_name (path_combine_and_normalize (exit_ob->map->path, EXIT_PATH (exit_ob)), 0);
842 /* Random map was previously generated, but is no longer about. Lets generate a new
843 * map.
844 */
845 if (!newmap && !strncmp (EXIT_PATH (exit_ob), "/random/", 8))
846 {
847 /* Maps that go down have a message set. However, maps that go
848 * up, don't. If the going home has reset, there isn't much
849 * point generating a random map, because it won't match the maps.
850 */
851 if (exit_ob->msg)
852 {
853 enter_random_map (op, exit_ob);
854 }
855 else
856 {
857 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name);
858 return;
859 }
860
861 /* For exits that cause damages (like pits). Don't know if any
862 * random maps use this or not.
863 */
864 if (exit_ob->stats.dam && op->type == PLAYER)
865 hit_player (op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
866 return;
867 }
868 }
869 else
870 {
871 /* For word of recall and other force objects
872 * They contain the full pathname of the map to go back to,
873 * so we don't need to normalize it.
874 * But we do need to see if it is unique or not
875 */
876 if (!strncmp (EXIT_PATH (exit_ob), settings.localdir, strlen (settings.localdir)))
877 newmap = ready_map_name (EXIT_PATH (exit_ob), MAP_PLAYER_UNIQUE);
878 else
879 newmap = ready_map_name (EXIT_PATH (exit_ob), 0);
880 }
881 if (!newmap)
882 {
883 if (exit_ob->name)
884 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", &exit_ob->name);
885 /* don't cry to momma if name is not set - as in tmp objects
886 * used by the savebed code and character creation */
887 return;
888 }
889
890 /* This supports the old behaviour, but it really should not be used.
891 * I will note for example that with this method, it is impossible to
892 * set 0,0 destination coordinates. Really, if we want to support
893 * using the new maps default coordinates, the exit ob should use
894 * something like -1, -1 so it is clear to do that.
895 */
896 if (x == 0 && y == 0)
897 {
898 x = MAP_ENTER_X (newmap);
899 y = MAP_ENTER_Y (newmap);
900 LOG (llevDebug, "enter_exit: Exit %s (%d,%d) on map %s is 0 destination coordinates\n",
901 &exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map ? exit_ob->map->path : "<nil>");
902 }
903
904 /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */
905 if (QUERY_FLAG (exit_ob, FLAG_DAMNED))
906 {
907 /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */
908 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
909 {
910 if (tmp->type == FORCE && tmp->slaying && !strcmp (tmp->slaying, PORTAL_DESTINATION_NAME))
911 break;
912 }
913 if (tmp)
914 {
915 remove_ob (tmp);
916 free_object (tmp);
917 }
918
919 strcpy (op->contr->savebed_map, path_combine_and_normalize (exit_ob->map->path, EXIT_PATH (exit_ob)));
920 op->contr->bed_x = EXIT_X (exit_ob), op->contr->bed_y = EXIT_Y (exit_ob);
921 save_player (op, 1);
922 /* LOG(llevDebug,"enter_exit: Taking damned exit %s to (%d,%d) on map %s\n",
923 * exit_ob->name?exit_ob->name:"(none)", exit_ob->x, exit_ob->y,
924 * path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob))); */
925 }
926
927 enter_map (op, newmap, x, y);
928 }
929 /* For exits that cause damages (like pits) */
930 if (exit_ob->stats.dam && op->type == PLAYER)
931 hit_player (op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
932 }
933 else
934 {
935 int flags = 0;
936 mapstruct *newmap;
937
938
939 /* Hypothetically, I guess its possible that a standard map matches
940 * the localdir, but that seems pretty unlikely - unlikely enough that
941 * I'm not going to attempt to try to deal with that possibility.
942 * We use the fact that when a player saves on a unique map, it prepends
943 * the localdir to that name. So its an easy way to see of the map is
944 * unique or not.
945 */
946 if (!strncmp (op->contr->maplevel, settings.localdir, strlen (settings.localdir)))
947 flags = MAP_PLAYER_UNIQUE;
948
949 /* newmap returns the map (if already loaded), or loads it for
950 * us.
951 */
952 newmap = ready_map_name (op->contr->maplevel, flags);
953 if (!newmap)
954 {
955 LOG (llevError, "enter_exit: Pathname to map does not exist! (%s)\n", op->contr->maplevel);
956 newmap = ready_map_name (settings.emergency_mapname, 0);
957 op->x = settings.emergency_x;
958 op->y = settings.emergency_y;
959 /* If we can't load the emergency map, something is probably really
960 * screwed up, so bail out now.
961 */
962 if (!newmap)
963 {
964 LOG (llevError, "enter_exit: could not load emergency map? Fatal error\n");
965 abort ();
966 }
967 }
968 enter_map (op, newmap, op->x, op->y);
969 }
970}
971
972/*
973 * process_active_maps(): Works like process_events(), but it only
974 * processes maps which a player is on.
975 *
976 */
977
978#if 0 // dead code, schmorp
979void
980process_active_maps ()
981{
982 for (mapstruct *map = first_map; map != NULL; map = map->next)
983 if (map->in_memory == MAP_IN_MEMORY)
984 if (players_on_map (map, TRUE))
985 process_events (map);
986}
987#endif
988 247
989/* process_players1 and process_players2 do all the player related stuff. 248/* process_players1 and process_players2 do all the player related stuff.
990 * I moved it out of process events and process_map. This was to some 249 * I moved it out of process events and process_map. This was to some
991 * extent for debugging as well as to get a better idea of the time used 250 * extent for debugging as well as to get a better idea of the time used
992 * by the various functions. process_players1() does the processing before 251 * by the various functions. process_players1() does the processing before
993 * objects have been updated, process_players2() does the processing that 252 * objects have been updated, process_players2() does the processing that
994 * is needed after the players have been updated. 253 * is needed after the players have been updated.
995 */ 254 */
996 255static void
997void 256process_players1 ()
998process_players1 (mapstruct *map)
999{ 257{
1000 int flag; 258 int flag;
1001 player *pl, *plnext;
1002 259
1003 /* Basically, we keep looping until all the players have done their actions. */ 260 /* Basically, we keep looping until all the players have done their actions. */
1004 for (flag = 1; flag != 0;) 261 for (flag = 1; flag != 0;)
1005 { 262 {
1006 flag = 0; 263 flag = 0;
1007 for (pl = first_player; pl != NULL; pl = plnext) 264 for_all_players (pl)
1008 { 265 {
1009 plnext = pl->next; /* In case a player exits the game in handle_player() */ 266 pl->refcnt_chk ();
1010 267
1011 if (pl->ob == NULL) 268 if (!pl->ob || !pl->ns || !pl->ob->active ())
1012 continue; 269 continue;
1013 270
1014 if (map != NULL && pl->ob->map != map)
1015 continue;
1016
1017 if (pl->ob->speed_left > 0) 271 if (pl->ob->speed_left > 0)
1018 {
1019 if (handle_newcs_player (pl->ob)) 272 if (handle_newcs_player (pl->ob))
1020 flag = 1; 273 flag = 1;
1021 } /* end if player has speed left */
1022 274
1023 /* If the player is not actively playing, don't make a 275 /* If the player is not actively playing, don't make a
1024 * backup save - nothing to save anyway. Plus, the 276 * backup save - nothing to save anyway. Plus, the
1025 * map may not longer be valid. This can happen when the 277 * map may not longer be valid. This can happen when the
1026 * player quits - they exist for purposes of tracking on the map, 278 * player quits - they exist for purposes of tracking on the map,
1031 283
1032#ifdef AUTOSAVE 284#ifdef AUTOSAVE
1033 /* check for ST_PLAYING state so that we don't try to save off when 285 /* check for ST_PLAYING state so that we don't try to save off when
1034 * the player is logging in. 286 * the player is logging in.
1035 */ 287 */
1036 if ((pl->last_save_tick + AUTOSAVE) < (uint32) pticks && pl->state == ST_PLAYING) 288 if ((pl->last_save_tick + AUTOSAVE) < (uint32) pticks && pl->ns->state == ST_PLAYING)
1037 { 289 {
1038 /* Don't save the player on unholy ground. Instead, increase the 290 pl->ob->contr->save ();
1039 * tick time so it will be about 10 seconds before we try and save
1040 * again.
1041 */
1042// if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL) & P_NO_CLERIC) {
1043// pl->last_save_tick += 100;
1044// } else {
1045 save_player (pl->ob, 1);
1046 pl->last_save_tick = pticks; 291 pl->last_save_tick = pticks;
1047// }
1048 } 292 }
1049#endif 293#endif
1050 } /* end of for loop for all the players */ 294 } /* end of for loop for all the players */
1051 } /* for flag */ 295 } /* for flag */
1052 for (pl = first_player; pl != NULL; pl = pl->next) 296
297 for_all_players (pl)
1053 { 298 {
1054 if (map != NULL && (pl->ob == NULL || pl->ob->map != map)) 299 if (!pl->ob || !pl->ns || !pl->ob->active ())
1055 continue; 300 continue;
301
1056 if (settings.casting_time == TRUE) 302 if (settings.casting_time)
1057 { 303 {
1058 if (pl->ob->casting_time > 0) 304 if (pl->ob->casting_time > 0)
1059 { 305 {
1060 pl->ob->casting_time--; 306 pl->ob->casting_time--;
1061 pl->ob->start_holding = 1; 307 pl->ob->start_holding = 1;
1062 } 308 }
309
1063 /* set spell_state so we can update the range in stats field */ 310 /* set spell_state so we can update the range in stats field */
1064 if ((pl->ob->casting_time == 0) && (pl->ob->start_holding == 1)) 311 if ((pl->ob->casting_time == 0) && (pl->ob->start_holding == 1))
1065 {
1066 pl->ob->start_holding = 0; 312 pl->ob->start_holding = 0;
1067 } 313 }
1068 } 314
1069 do_some_living (pl->ob); 315 do_some_living (pl->ob);
1070 /* draw(pl->ob); *//* updated in socket code */
1071 } 316 }
1072} 317}
1073 318
1074void 319static void
1075process_players2 (mapstruct *map) 320process_players2 ()
1076{ 321{
1077 player *pl;
1078
1079 /* Then check if any players should use weapon-speed instead of speed */ 322 /* Then check if any players should use weapon-speed instead of speed */
1080 for (pl = first_player; pl != NULL; pl = pl->next) 323 for_all_players (pl)
1081 { 324 {
1082 if (map != NULL)
1083 {
1084 if (pl->ob == NULL || QUERY_FLAG (pl->ob, FLAG_REMOVED))
1085 continue;
1086 else if (pl->loading != NULL) /* Player is blocked */
1087 pl->ob->speed_left -= pl->ob->speed;
1088 if (pl->ob->map != map)
1089 continue;
1090 }
1091
1092 /* The code that did weapon_sp handling here was out of place - 325 /* The code that did weapon_sp handling here was out of place -
1093 * this isn't called until after the player has finished there 326 * this isn't called until after the player has finished there
1094 * actions, and is thus out of place. All we do here is bounds 327 * actions, and is thus out of place. All we do here is bounds
1095 * checking. 328 * checking.
1096 */ 329 */
1102 /* This needs to be here - if the player is running, we need to 335 /* This needs to be here - if the player is running, we need to
1103 * clear this each tick, but new commands are not being received 336 * clear this each tick, but new commands are not being received
1104 * so execute_newserver_command() is never called 337 * so execute_newserver_command() is never called
1105 */ 338 */
1106 pl->has_hit = 0; 339 pl->has_hit = 0;
1107
1108 } 340 }
1109 else if (pl->ob->speed_left > pl->ob->speed) 341 else if (pl->ob->speed_left > pl->ob->speed)
1110 pl->ob->speed_left = pl->ob->speed; 342 pl->ob->speed_left = pl->ob->speed;
1111 } 343 }
1112} 344}
1113 345
1114void 346void
1115process_events (mapstruct *map) 347process_events ()
1116{ 348{
1117 object *op; 349 object *op;
1118 object *marker = get_object ();
1119 tag_t tag;
1120 350
351 static object_ptr marker_;
352
353 if (!marker_)
354 marker_ = object::create ();
355
356 object *marker = marker_;
357
1121 process_players1 (map); 358 process_players1 ();
1122 359
1123 marker->active_next = active_objects; 360 marker->active_next = active_objects;
1124 361
1125 if (marker->active_next) 362 if (marker->active_next)
1126 marker->active_next->active_prev = marker; 363 marker->active_next->active_prev = marker;
1127 364
1128 marker->active_prev = NULL; 365 marker->active_prev = 0;
1129 active_objects = marker; 366 active_objects = marker;
1130 367
1131 while (marker->active_next) 368 while (marker->active_next)
1132 { 369 {
1133 op = marker->active_next; 370 op = marker->active_next;
1134 tag = op->count;
1135 371
1136 /* Move marker forward - swap op and marker */ 372 /* Move marker forward - swap op and marker */
1137 op->active_prev = marker->active_prev; 373 op->active_prev = marker->active_prev;
1138 374
1139 if (op->active_prev) 375 if (op->active_prev)
1151 387
1152 /* Now process op */ 388 /* Now process op */
1153 if (QUERY_FLAG (op, FLAG_FREED)) 389 if (QUERY_FLAG (op, FLAG_FREED))
1154 { 390 {
1155 LOG (llevError, "BUG: process_events(): Free object on list\n"); 391 LOG (llevError, "BUG: process_events(): Free object on list\n");
1156 op->speed = 0; 392 op->set_speed (0);
1157 update_ob_speed (op);
1158 continue; 393 continue;
1159 } 394 }
1160 395
1161 /* I've seen occasional crashes due to this - the object is removed, 396 /* I've seen occasional crashes due to this - the object is removed,
1162 * and thus the map it points to (last map it was on) may be bogus 397 * and thus the map it points to (last map it was on) may be bogus
1169 * around. 404 * around.
1170 */ 405 */
1171 if (QUERY_FLAG (op, FLAG_REMOVED) && op->type != PLAYER && op->map && op->map->in_memory != MAP_IN_MEMORY) 406 if (QUERY_FLAG (op, FLAG_REMOVED) && op->type != PLAYER && op->map && op->map->in_memory != MAP_IN_MEMORY)
1172 { 407 {
1173 LOG (llevError, "BUG: process_events(): Removed object on list\n"); 408 LOG (llevError, "BUG: process_events(): Removed object on list\n");
1174 dump_object (op); 409 char *dump = dump_object (op);
1175 LOG (llevError, errmsg); 410 LOG (llevError, dump);
1176 free_object (op); 411 free (dump);
412 op->destroy ();
1177 continue; 413 continue;
1178 } 414 }
1179 415
1180 if (!op->speed) 416 if (!op->has_active_speed ())
1181 { 417 {
1182 LOG (llevError, "BUG: process_events(): Object %s has no speed, " "but is on active list\n", &op->arch->name); 418 LOG (llevError, "BUG: process_events(): Object %s has no speed (%f), "
1183 update_ob_speed (op); 419 "but is on active list\n", op->debug_desc (), op->speed);
420 op->set_speed (0);
1184 continue; 421 continue;
1185 } 422 }
1186 423
1187 if (op->map == NULL && op->env == NULL && op->name && op->type != MAP && map == NULL) 424 if (op->map == NULL && op->env == NULL && op->name && op->type != MAP)
1188 { 425 {
1189 LOG (llevError, "BUG: process_events(): Object without map or " "inventory is on active list: %s (%d)\n", &op->name, op->count); 426 LOG (llevError, "BUG: process_events(): Object without map or "
427 "inventory is on active list: %s (%d)\n", &op->name, op->count);
1190 op->speed = 0; 428 op->set_speed (0);
1191 update_ob_speed (op);
1192 continue; 429 continue;
1193 } 430 }
1194 431
1195 if (map != NULL && op->map != map)
1196 continue;
1197
1198 /* Animate the object. Bug of feature that andim_speed 432 /* Animate the object. Bug or feature that anim_speed
1199 * is based on ticks, and not the creatures speed? 433 * is based on ticks, and not the creatures speed?
1200 */ 434 */
1201 if (op->anim_speed && op->last_anim >= op->anim_speed) 435 if (op->anim_speed && op->last_anim >= op->anim_speed)
1202 { 436 {
1203 if ((op->type == PLAYER) || (op->type == MONSTER)) 437 if ((op->type == PLAYER))
1204 animate_object (op, op->facing); 438 animate_object (op, op->facing);
1205 else 439 else
1206 animate_object (op, op->direction); 440 animate_object (op, op->direction);
1207 441
1208 op->last_anim = 1; 442 op->last_anim = 1;
1226 LOG (llevDebug, "process_events: calling process_object with removed object %s\n", op->name ? op->name : "null"); 460 LOG (llevDebug, "process_events: calling process_object with removed object %s\n", op->name ? op->name : "null");
1227 } 461 }
1228#endif 462#endif
1229 --op->speed_left; 463 --op->speed_left;
1230 process_object (op); 464 process_object (op);
465
1231 if (was_destroyed (op, tag)) 466 if (op->destroyed ())
1232 continue; 467 continue;
1233 } 468 }
469
1234 if (settings.casting_time == TRUE && op->casting_time > 0) 470 if (settings.casting_time == TRUE && op->casting_time > 0)
1235 op->casting_time--; 471 op->casting_time--;
472
1236 if (op->speed_left <= 0) 473 if (op->speed_left <= 0)
1237 op->speed_left += FABS (op->speed); 474 op->speed_left += FABS (op->speed);
1238 } 475 }
1239 476
1240 /* Remove marker object from active list */ 477 /* Remove marker object from active list */
1241 if (marker->active_prev != NULL) 478 if (marker->active_prev != NULL)
1242 marker->active_prev->active_next = NULL; 479 marker->active_prev->active_next = NULL;
1243 else 480 else
1244 active_objects = NULL; 481 active_objects = NULL;
1245 482
1246 process_players2 (map); 483 process_players2 ();
1247
1248 free_object (marker);
1249}
1250
1251void
1252clean_tmp_files (void)
1253{
1254 mapstruct *m, *next;
1255
1256 LOG (llevInfo, "Cleaning up...\n");
1257
1258 /* We save the maps - it may not be intuitive why, but if there are unique
1259 * items, we need to save the map so they get saved off. Perhaps we should
1260 * just make a special function that only saves the unique items.
1261 */
1262 for (m = first_map; m != NULL; m = next)
1263 {
1264 next = m->next;
1265 if (m->in_memory == MAP_IN_MEMORY)
1266 {
1267 /* If we want to reuse the temp maps, swap it out (note that will also
1268 * update the log file. Otherwise, save the map (mostly for unique item
1269 * stuff). Note that the clean_tmp_map is called after the end of
1270 * the for loop but is in the #else bracket. IF we are recycling the maps,
1271 * we certainly don't want the temp maps removed.
1272 */
1273
1274 /* XXX The above comment is dead wrong */
1275 if (settings.recycle_tmp_maps == TRUE)
1276 swap_map (m);
1277 else
1278 {
1279 new_save_map (m, 0); /* note we save here into a overlay map */
1280 clean_tmp_map (m);
1281 }
1282 }
1283 }
1284 write_todclock (); /* lets just write the clock here */
1285} 484}
1286 485
1287/* clean up everything before exiting */ 486/* clean up everything before exiting */
1288void 487void
1289cleanup (void) 488emergency_save ()
1290{ 489{
1291 LOG (llevDebug, "Cleanup called. freeing data.\n"); 490 LOG (llevDebug, "emergency save begin.\n");
1292 clean_tmp_files (); 491
492 LOG (llevDebug, "saving players.\n");
493 for_all_players (pl)
494 if (pl->enable_save && pl->ob && pl->ns)
495 {
496 pl->save (true);
497 pl->enable_save = true;
498 }
499
500// for_all_players (pl)
501// if (pl->ob)
502// pl->ob->remove ();
503
504 LOG (llevDebug, "saving maps.\n");
505 maptile::emergency_save ();
506
507 LOG (llevDebug, "saving book archive.\n");
1293 write_book_archive (); 508 write_book_archive ();
1294#ifdef MEMORY_DEBUG
1295 free_all_maps ();
1296 free_style_maps ();
1297 free_all_object_data ();
1298 free_all_archs ();
1299 free_all_treasures ();
1300 free_all_images ();
1301 free_all_newserver ();
1302 free_all_recipes ();
1303 free_all_readable ();
1304 free_all_god ();
1305 free_all_anim ();
1306 /* See what the string data that is out there that hasn't been freed. */
1307 509
1308/* LOG(llevDebug, ss_dump_table(0xff));*/ 510 LOG (llevDebug, "emergency save done.\n");
1309#endif 511}
512
513// send all clients some informational text
514static void
515cleanup_inform (const char *cause, bool make_core)
516{
517 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_RED, 0, 0, "The server will now shutdown.\n");
518 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_RED, 0, 0, "Cause for this shtudown: %s\n", cause);
519
520 if (make_core)
521 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_RED, 0, 0, "This is considered a crash.\n");
522 else
523 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_RED, 0, 0, "This is considered to be a clean shutdown.\n");
524
525 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_RED, 0, 0, "%s\n", CLEANUP_MESSAGE);
526
527 flush_sockets ();
528}
529
530/* clean up everything before exiting */
531void
532cleanup (const char *cause, bool make_core)
533{
534 LOG (llevError, "cleanup cause: %s\n", cause);
535
536 if (!make_core)
537 cleanup_inform (cause, make_core);
538
539 LOG (llevDebug, "cleanup begin.\n");
540
541 if (init_done && !in_cleanup)
542 {
543 in_cleanup = true;
544 emergency_save ();
545 }
546 else
547 in_cleanup = true;
548
549 LOG (llevDebug, "running cleanup handlers.\n");
550 INVOKE_GLOBAL (CLEANUP);
551
552 LOG (llevDebug, "cleanup done.\n");
553
554 if (make_core)
555 {
556 cleanup_inform (cause, make_core);
557 abort ();
558 }
559 else
1310 exit (0); 560 _exit (0);
1311}
1312
1313void
1314leave (player *pl, int draw_exit)
1315{
1316 if (pl != NULL)
1317 {
1318 /* We do this so that the socket handling routine can do the final
1319 * cleanup. We also leave that loop to actually handle the freeing
1320 * of the data.
1321 */
1322 if (pl->ob->type != DEAD_OBJECT)
1323 {
1324 pl->socket.status = Ns_Dead;
1325
1326 /* If a hidden dm dropped connection do not create
1327 * inconsistencies by showing that they have left the game
1328 */
1329 if (!(QUERY_FLAG (pl->ob, FLAG_WIZ) && pl->ob->contr->hidden)
1330 && draw_exit && (pl->state != ST_GET_NAME && pl->state != ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD))
1331 {
1332 if (pl->ob->map)
1333 {
1334 INVOKE_PLAYER (LOGOUT, pl);
1335 LOG (llevInfo, "LOGOUT: Player named %s from ip %s\n", &pl->ob->name, pl->socket.host);
1336 }
1337
1338 char buf[MAX_BUF];
1339
1340 sprintf (buf, "%s left the game.", &pl->ob->name);
1341 new_draw_info (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, buf);
1342 }
1343
1344 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED))
1345 leave_map (pl->ob);
1346
1347 pl->ob->type = DEAD_OBJECT; /* To avoid problems with inventory window */
1348 }
1349 }
1350} 561}
1351 562
1352int 563int
1353forbid_play (void) 564forbid_play (void)
1354{ 565{
1368 579
1369 while (fgets (buf, MAX_BUF, fp)) 580 while (fgets (buf, MAX_BUF, fp))
1370 { 581 {
1371 if (buf[0] == '#') 582 if (buf[0] == '#')
1372 continue; 583 continue;
584
1373 if (!strncmp (buf, "msg", 3)) 585 if (!strncmp (buf, "msg", 3))
1374 { 586 {
1375 if (forbit) 587 if (forbit)
1376 while (fgets (buf, MAX_BUF, fp)) /* print message */ 588 while (fgets (buf, MAX_BUF, fp)) /* print message */
1377 fputs (buf, logfile); 589 fputs (buf, logfile);
1378 break; 590 break;
1379
1380 } 591 }
1381 else if (sscanf (buf, "%s %d%*c%d\n", day, &start, &stop) != 3) 592 else if (sscanf (buf, "%s %d%*c%d\n", day, &start, &stop) != 3)
1382 { 593 {
1383 LOG (llevDebug, "Warning: Incomplete line in permission file ignored.\n"); 594 LOG (llevDebug, "Warning: Incomplete line in permission file ignored.\n");
1384 continue; 595 continue;
1398 return 0; 609 return 0;
1399#endif 610#endif
1400} 611}
1401 612
1402/* 613/*
1403 * do_specials() is a collection of functions to call from time to time. 614 * do_specials() is a collection of functions to call from time to time.
1404 * Modified 2000-1-14 MSW to use the global pticks count to determine how 615 * Modified 2000-1-14 MSW to use the global pticks count to determine how
1405 * often to do things. This will allow us to spred them out more often. 616 * often to do things. This will allow us to spred them out more often.
1406 * I use prime numbers for the factor count - in that way, it is less likely 617 * I use prime numbers for the factor count - in that way, it is less likely
1407 * these actions will fall on the same tick (compared to say using 500/2500/15000 618 * these actions will fall on the same tick (compared to say using 500/2500/15000
1408 * which would mean on that 15,000 tick count a whole bunch of stuff gets 619 * which would mean on that 15,000 tick count a whole bunch of stuff gets
1416extern unsigned long todtick; 627extern unsigned long todtick;
1417 628
1418void 629void
1419do_specials (void) 630do_specials (void)
1420{ 631{
1421
1422#ifdef WATCHDOG
1423 if (!(pticks % 503))
1424 watchdog ();
1425#endif
1426
1427 if (!(pticks % PTICKS_PER_CLOCK)) 632 if (!(pticks % PTICKS_PER_CLOCK))
1428 tick_the_clock (); 633 tick_the_clock ();
1429 634
1430 if (!(pticks % 7)) 635 if (!(pticks % 7))
1431 shstr::gc (); 636 shstr::gc ();
1432 637
1433 if (!(pticks % 79))
1434 flush_old_maps (); /* Clears the tmp-files of maps which have reset */
1435
1436 if (!(pticks % 2503)) 638 if (!(pticks % 2503))
1437 fix_weight (); /* Hack to fix weightproblems caused by bugs */ 639 fix_weight (); /* Hack to fix weightproblems caused by bugs */
1438 640
1439 if (!(pticks % 2521))
1440 metaserver_update (); /* 2500 ticks is about 5 minutes */
1441
1442 if (!(pticks % 5003)) 641 if (!(pticks % 5003))
1443 write_book_archive (); 642 write_book_archive ();
1444 643
1445 if (!(pticks % 5009)) 644 if (!(pticks % 5009))
1446 clean_friendly_list (); 645 clean_friendly_list ();
1453} 652}
1454 653
1455void 654void
1456server_tick () 655server_tick ()
1457{ 656{
1458 nroferrors = 0; 657 // first do the user visible stuff
1459
1460 doeric_server (); 658 doeric_server ();
1461 INVOKE_GLOBAL (CLOCK); 659 INVOKE_GLOBAL (CLOCK);
1462 process_events (NULL); /* "do" something with objects with speed */ 660 process_events (); /* "do" something with objects with speed */
1463 flush_sockets (); 661 flush_sockets ();
1464 check_active_maps (); /* Removes unused maps after a certain timeout */ 662
663 // then do some bookkeeping, should not really be here
1465 do_specials (); /* Routines called from time to time. */ 664 do_specials (); /* Routines called from time to time. */
1466 object::free_mortals (); 665 attachable::check_mortals ();
1467 666
1468 ++pticks; 667 ++pticks;
1469} 668}
1470 669
1471int 670int
1472main (int argc, char **argv) 671main (int argc, char **argv)
1473{ 672{
1474 settings.argc = argc; 673 settings.argc = argc;
1475 settings.argv = argv; 674 settings.argv = argv;
1476 675
1477 cfperl_init ();
1478
1479 init (argc, argv); 676 init (argc, argv);
1480 677
1481 initPlugins (); 678 initPlugins ();
1482 679
1483 for (;;) 680 for (;;)
1484 cfperl_main (); 681 cfperl_main ();
1485
1486 // unreached
1487 emergency_save (0);
1488 cleanup ();
1489
1490 return 0;
1491} 682}
683

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines