ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/swap.c
Revision: 1.5
Committed: Sun Aug 13 17:16:05 2006 UTC (17 years, 9 months ago) by elmex
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
State: FILE REMOVED
Log Message:
Made server compile with C++.
Removed cfanim plugin and crossedit.
C++ here we come.

File Contents

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