ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/swap.C
Revision: 1.19
Committed: Wed Dec 27 18:09:49 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.18: +7 -9 lines
Log Message:
i cannot find, nor reproduce, the problem at all.
the log clearly shows map loads where there shouldn't be any, so we lose maps.
but only on cf.schmorp.de.
i am frustrated.

File Contents

# Content
1 /*
2 CrossFire, A Multiplayer game for X-windows
3
4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5 Copyright (C) 1992 Frank Tore Johansen
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 The author can be reached via e-mail to <crossfire@schmorp.de>
22 */
23
24 #include <global.h>
25 #include <sproto.h>
26 #include <object.h>
27
28 /* This writes out information on all the temporary maps. It is called by
29 * swap_map below.
30 */
31 static void
32 write_map_log (void)
33 {
34 FILE *fp;
35 maptile *map;
36 char buf[MAX_BUF];
37 long current_time = time (NULL);
38
39 sprintf (buf, "%s/temp.maps", settings.localdir);
40 if (!(fp = fopen (buf, "w")))
41 {
42 LOG (llevError, "Could not open %s for writing\n", buf);
43 return;
44 }
45
46 for_all_maps (map)
47 /* If tmpname is null, it is probably a unique player map,
48 * so don't save information on it.
49 */
50 if (map->in_memory != MAP_IN_MEMORY && map->tmpname)
51 /* the 0 written out is a leftover from the lock number for
52 * unique items and second one is from encounter maps.
53 * Keep using it so that old temp files continue
54 * to work.
55 */
56 fprintf (fp, "%s:%s:%ld:0:0:%d:0:%d\n", map->path, map->tmpname,
57 (map->reset_time == (uint32) - 1 ? (long unsigned) -1 : map->reset_time - current_time), map->difficulty, map->darkness);
58
59 fclose (fp);
60 }
61
62 void
63 read_map_log (void)
64 {
65 FILE *fp;
66 maptile *map;
67 char buf[MAX_BUF], *cp, *cp1;
68 int do_los, darkness, lock;
69 long sec = time (0);
70
71 sprintf (buf, "%s/temp.maps", settings.localdir);
72 if (!(fp = fopen (buf, "r")))
73 {
74 LOG (llevDebug, "Could not open %s for reading\n", buf);
75 return;
76 }
77
78 while (fgets (buf, MAX_BUF, fp))
79 {
80 map = get_linked_map ();
81 /* scanf doesn't work all that great on strings, so we break
82 * out that manually. strdup is used for tmpname, since other
83 * routines will try to free that pointer.
84 */
85 cp = strchr (buf, ':');
86 *cp++ = '\0';
87 strcpy (map->path, buf);
88 cp1 = strchr (cp, ':');
89 *cp1++ = '\0';
90 map->tmpname = strdup (cp);
91
92 /* Lock is left over from the lock items - we just toss it now.
93 * We use it twice - second one is from encounter, but as we
94 * don't care about the value, this works fine
95 */
96 sscanf (cp1, "%d:%d:%d:%hd:%d:%d\n", &map->reset_time, &lock, &lock, &map->difficulty, &do_los, &darkness);
97
98 map->in_memory = MAP_SWAPPED;
99 map->darkness = darkness;
100
101 /* When the reset time is saved out, it is adjusted so that
102 * the current time is subtracted (thus, it is saved as number
103 * of seconds from current time that it should reset). We need
104 * to add in the current seconds for this to work right.
105 * On metalforge, strange behavior was observed with really high
106 * reset times - I don't know how they got to that state,
107 * but easy enough to do some sanity checking here.
108 */
109 map->reset_time += sec;
110 if (map->reset_time > (uint32) (sec + MAP_MAXRESET))
111 map->reset_time = 0;
112 }
113
114 fclose (fp);
115 }
116
117 void
118 swap_map (maptile *map)
119 {
120 if (map->in_memory != MAP_IN_MEMORY)
121 {
122 LOG (llevError, "Tried to swap out map which was not in memory.\n");
123 return;
124 }
125
126 // cannot (yet) swap out maps with players
127 for_all_players (pl)
128 if (pl->ob && pl->ob->map == map && !pl->ob->flag [FLAG_REMOVED])
129 return;
130
131 remove_all_pets (map); /* Give them a chance to follow */
132
133 /* Update the reset time. Only do this if STAND_STILL is not set */
134 if (!map->fixed_resettime)
135 set_map_reset_time (map);
136
137 /* If it is immediate reset time, don't bother saving it - just get
138 * rid of it right away.
139 */
140 if (map->reset_time <= (uint32) time (0))
141 {
142 LOG (llevDebug, "Resetting map %s.\n", map->path);
143 INVOKE_MAP (RESET, map);
144 delete_map (map);
145 return;
146 }
147
148 if (new_save_map (map, 0) == -1)
149 {
150 LOG (llevError, "Failed to swap map %s.\n", map->path);
151 /* need to reset the in_memory flag so that delete map will also
152 * free the objects with it.
153 */
154 map->in_memory = MAP_IN_MEMORY;
155 delete_map (map);
156 }
157 else
158 {
159 INVOKE_MAP (SWAPOUT, map);
160 free_map (map, 1);
161 }
162
163 write_map_log ();
164 }
165
166 void
167 check_active_maps (void)
168 {
169 for_all_maps (map)
170 if (map->in_memory == MAP_IN_MEMORY
171 && map->timeout
172 && !--map->timeout)
173 {
174 swap_map (map);
175 // only swap one map per tick
176 break;
177 }
178 }
179
180 /*
181 * map_least_timeout() returns the map with the lowest timeout variable (not 0)
182 */
183 maptile *
184 map_least_timeout (char *except_level)
185 {
186 maptile *chosen = NULL;
187 int timeout = MAP_MAXTIMEOUT + 1;
188
189 for_all_maps (map)
190 if (map->in_memory == MAP_IN_MEMORY && strcmp (map->path, except_level) && map->timeout && map->timeout < timeout)
191 chosen = map, timeout = map->timeout;
192
193 return chosen;
194 }
195
196 /*
197 * players_on_map(): will be replaced by map->players when I'm satisfied
198 * that the variable is always correct.
199 * If show_all is true, we show everyone. If not, we don't show hidden
200 * players (dms)
201 */
202 int
203 players_on_map (maptile *m, int show_all)
204 {
205 int nr = 0;
206
207 for_all_players (pl)
208 if (pl->ob != NULL && !QUERY_FLAG (pl->ob, FLAG_REMOVED) && pl->ob->map == m && (show_all || !pl->hidden))
209 nr++;
210
211 return nr;
212 }
213
214 /*
215 * flush_old_maps():
216 * Removes tmp-files of maps which are going to be reset next time
217 * they are visited.
218 * This is very useful if the tmp-disk is very full.
219 */
220 void
221 flush_old_maps (void)
222 {
223 maptile *m, *oldmap;
224 uint32 sec = time (0);
225
226 m = first_map;
227 while (m)
228 {
229 /* There can be cases (ie death) where a player leaves a map and the timeout
230 * is not set so it isn't swapped out.
231 */
232 if ((m->in_memory == MAP_IN_MEMORY) && (m->timeout == 0) && !players_on_map (m, TRUE))
233 set_map_timeout (m);
234
235 /* per player unique maps are never really reset. However, we do want
236 * to perdiocially remove the entries in the list of active maps - this
237 * generates a cleaner listing if a player issues the map commands, and
238 * keeping all those swapped out per player unique maps also has some
239 * memory and cpu consumption.
240 * We do the cleanup here because there are lots of places that call
241 * swap map, and doing it within swap map may cause problems as
242 * the functions calling it may not expect the map list to change
243 * underneath them.
244 */
245 if ((m->unique || m->templatemap) && m->in_memory == MAP_SWAPPED)
246 {
247 LOG (llevDebug, "Resetting map %s.\n", m->path);
248 oldmap = m;
249 m = m->next;
250 delete_map (oldmap);
251 }
252 else if (m->in_memory != MAP_SWAPPED || m->tmpname == NULL || sec < m->reset_time)
253 m = m->next;
254 else
255 {
256 LOG (llevDebug, "Resetting map %s.\n", m->path);
257 INVOKE_MAP (RESET, m);
258 clean_tmp_map (m);
259 oldmap = m;
260 m = m->next;
261 delete_map (oldmap);
262 }
263 }
264 }