ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.35
Committed: Mon Dec 25 17:11:17 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.34: +1 -1 lines
Log Message:
- some fixes
- disable some refcounting again, not ready yet
- simplify save_object

File Contents

# User Rev Content
1 elmex 1.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 root 1.18 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     #include <global.h>
25 root 1.30 #include <sproto.h>
26 elmex 1.1 #include <spells.h>
27     #include <loader.h>
28     #include <define.h>
29    
30     extern void sub_weight (object *, signed long);
31     extern void add_weight (object *, signed long);
32     extern long pticks;
33    
34     /* If flag is non zero, it means that we want to try and save everyone, but
35     * keep the game running. Thus, we don't want to free any information.
36     */
37 root 1.15 void
38     emergency_save (int flag)
39     {
40 elmex 1.1 trying_emergency_save = 1;
41 root 1.30
42 root 1.15 LOG (llevError, "Emergency save: ");
43 root 1.34 for_all_players (pl)
44 root 1.15 {
45     if (!pl->ob)
46     {
47     LOG (llevError, "No name, ignoring this.\n");
48     continue;
49     }
50 root 1.30
51     LOG (llevError, "%s ", &pl->ob->name);
52 root 1.15 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save...");
53 elmex 1.1
54 root 1.30 /* If we are not exiting the game (ie, this is sort of a backup save), then
55     * don't change the location back to the village. Note that there are other
56     * options to have backup saves be done at the starting village
57     */
58 root 1.15 if (!flag)
59     {
60     strcpy (pl->maplevel, first_map_path);
61 root 1.30
62 root 1.31 pl->ob->map = 0;
63 root 1.15 pl->ob->x = -1;
64     pl->ob->y = -1;
65     }
66 root 1.30
67     pl->save (1);
68 elmex 1.1 }
69 root 1.30
70 root 1.15 LOG (llevError, "\n");
71 elmex 1.1 }
72    
73     /* Delete character with name. if new is set, also delete the new
74     * style directory, otherwise, just delete the old style playfile
75     * (needed for transition)
76     */
77 root 1.15 void
78     delete_character (const char *name, int newchar)
79     {
80     char buf[MAX_BUF];
81 elmex 1.1
82 root 1.15 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
83 root 1.30
84 root 1.15 if (unlink (buf) == -1)
85     LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
86 root 1.30
87 root 1.15 if (newchar)
88     {
89     sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
90     /* this effectively does an rm -rf on the directory */
91     remove_directory (buf);
92 elmex 1.1 }
93     }
94    
95 root 1.15 int
96     create_savedir_if_needed (char *savedir)
97 elmex 1.1 {
98     struct stat *buf;
99    
100 root 1.15 if ((buf = (struct stat *) malloc (sizeof (struct stat))) == NULL)
101     {
102     LOG (llevError, "Unable to save playerfile... out of memory.\n");
103     return 0;
104     }
105     else
106     {
107     stat (savedir, buf);
108     if (!S_ISDIR (buf->st_mode))
109     if (mkdir (savedir, SAVE_DIR_MODE))
110     {
111     LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno));
112     return 0;
113     }
114     free (buf);
115     }
116 root 1.30
117 root 1.15 return 1;
118 elmex 1.1 }
119    
120     /*
121 root 1.30 * If final is set, it a clean/final save, not a backup, ie dont remove objects from inventory
122 elmex 1.1 */
123 root 1.30 void
124     player::save (bool final)
125 root 1.15 {
126 root 1.30 object *tmp, *container = 0;
127 root 1.15
128     /* Sanity check - some stuff changes this when player is exiting */
129 root 1.30 if (ob->type != PLAYER || !enable_save || !ns)
130     return;
131 elmex 1.1
132 root 1.30 INVOKE_PLAYER (SAVE, ob->contr);
133 root 1.5
134 root 1.30 object_freezer freezer;
135 elmex 1.1
136 root 1.33 int wiz = ob->flag [FLAG_WIZ];
137 root 1.3
138 root 1.9 /* Eneq(@csd.uu.se): If we have an open container hide it. */
139 root 1.30 container = ob->container;
140     ob->container = 0;
141    
142     fprintf (freezer, "password %s\n", password);
143 elmex 1.1
144 root 1.30 if (own_title[0] != '\0')
145     fprintf (freezer, "title %s\n", own_title);
146 root 1.3
147 root 1.30 fprintf (freezer, "explore %d\n", explore);
148     fprintf (freezer, "gen_hp %d\n", gen_hp);
149     fprintf (freezer, "gen_sp %d\n", gen_sp);
150     fprintf (freezer, "gen_grace %d\n", gen_grace);
151     fprintf (freezer, "listening %d\n", listening);
152     fprintf (freezer, "shoottype %d\n", shoottype);
153     fprintf (freezer, "bowtype %d\n", bowtype);
154     fprintf (freezer, "petmode %d\n", petmode);
155     fprintf (freezer, "peaceful %d\n", peaceful);
156     fprintf (freezer, "digestion %d\n", digestion);
157     fprintf (freezer, "pickup %d\n", mode);
158     fprintf (freezer, "outputs_sync %d\n", outputs_sync);
159     fprintf (freezer, "outputs_count %d\n", outputs_count);
160 elmex 1.1 /* Match the enumerations but in string form */
161 root 1.30 fprintf (freezer, "usekeys %s\n", usekeys == key_inventory ? "key_inventory" : (usekeys == keyrings ? "keyrings" : "containers"));
162 elmex 1.1 /* Match the enumerations but in string form */
163 root 1.30 fprintf (freezer, "unapply %s\n", unapply == unapply_nochoice ? "unapply_nochoice" :
164     (unapply == unapply_never ? "unapply_never" : "unapply_always"));
165 elmex 1.1
166 root 1.30 if (ob->map)
167     fprintf (freezer, "map %s\n", ob->map->path);
168 elmex 1.1 else
169 root 1.15 fprintf (freezer, "map %s\n", settings.emergency_mapname);
170    
171 root 1.30 fprintf (freezer, "savebed_map %s\n", savebed_map);
172     fprintf (freezer, "bed_x %d\nbed_y %d\n", bed_x, bed_y);
173     fprintf (freezer, "weapon_sp %f\n", weapon_sp);
174     fprintf (freezer, "Str %d\n", orig_stats.Str);
175     fprintf (freezer, "Dex %d\n", orig_stats.Dex);
176     fprintf (freezer, "Con %d\n", orig_stats.Con);
177     fprintf (freezer, "Int %d\n", orig_stats.Int);
178     fprintf (freezer, "Pow %d\n", orig_stats.Pow);
179     fprintf (freezer, "Wis %d\n", orig_stats.Wis);
180     fprintf (freezer, "Cha %d\n", orig_stats.Cha);
181    
182     fprintf (freezer, "lev_array %d\n", ob->level > 10 ? 10 : ob->level);
183    
184     for (int i = 1; i <= last_level && i <= 10; i++)
185     {
186     fprintf (freezer, "%d\n", levhp[i]);
187     fprintf (freezer, "%d\n", levsp[i]);
188     fprintf (freezer, "%d\n", levgrace[i]);
189 root 1.15 }
190 root 1.4
191 root 1.30 freezer.put (ob->contr);
192 root 1.4
193 root 1.15 fprintf (freezer, "endplst\n");
194 elmex 1.1
195 root 1.30 SET_FLAG (ob, FLAG_NO_FIX_PLAYER);
196     CLEAR_FLAG (ob, FLAG_WIZ);
197 root 1.35 save_object (freezer, ob, 1); /* don't check and don't remove */
198 elmex 1.1
199 root 1.9 char filename[MAX_BUF];
200 root 1.15
201 root 1.30 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &ob->name, &ob->name);
202 root 1.15 make_path_to_file (filename);
203 root 1.9 freezer.save (filename);
204    
205 root 1.30 CLEAR_FLAG (ob, FLAG_NO_FIX_PLAYER);
206 elmex 1.1
207     /* Eneq(@csd.uu.se): Reveal the container if we have one. */
208 root 1.30 ob->container = container;
209 root 1.5
210 root 1.33 ob->flag [FLAG_WIZ] = wiz;
211 elmex 1.1
212 root 1.30 enable_save = !final;
213 elmex 1.1 }
214    
215 root 1.30 player *
216     player::load (const char *path)
217 root 1.15 {
218 root 1.30 object_thawer thawer (path);
219 root 1.15
220     /* If no file, must be a new player, so lets get confirmation of
221     * the password. Return control to the higher level dispatch,
222     * since the rest of this just deals with loading of the file.
223     */
224     if (!thawer)
225 root 1.30 return 0;
226 root 1.3
227 root 1.30 player *pl = new player;
228 root 1.16
229 root 1.30 char buf[MAX_BUF], bufall[MAX_BUF];
230 root 1.19
231 root 1.30 pl->set_object (object::create ());
232     pl->last_save_time = time (0);
233 elmex 1.1
234 root 1.30 assign (pl->savebed_map, first_map_path);
235 root 1.15
236     /* Loop through the file, loading the rest of the values */
237 root 1.30 while (fgets (bufall, MAX_BUF, thawer))
238 root 1.15 {
239 root 1.30 int value;
240 root 1.15 sscanf (bufall, "%s %d\n", buf, &value);
241 root 1.30
242 root 1.15 if (!strcmp (buf, "endplst"))
243     break;
244     else if (!strcmp (buf, "oid"))
245     thawer.get (pl, value);
246 root 1.30 else if (!strcmp (buf, "password"))
247     sscanf (bufall, "password %[^\n]", pl->password);
248     else if (!strcmp (buf, "title"))
249 root 1.15 sscanf (bufall, "title %[^\n]", pl->own_title);
250     else if (!strcmp (buf, "explore"))
251     pl->explore = value;
252     else if (!strcmp (buf, "gen_hp"))
253     pl->gen_hp = value;
254     else if (!strcmp (buf, "shoottype"))
255     pl->shoottype = (rangetype) value;
256     else if (!strcmp (buf, "bowtype"))
257     pl->bowtype = (bowtype_t) value;
258     else if (!strcmp (buf, "petmode"))
259     pl->petmode = (petmode_t) value;
260     else if (!strcmp (buf, "gen_sp"))
261     pl->gen_sp = value;
262     else if (!strcmp (buf, "gen_grace"))
263     pl->gen_grace = value;
264     else if (!strcmp (buf, "listening"))
265     pl->listening = value;
266     else if (!strcmp (buf, "peaceful"))
267     pl->peaceful = value;
268     else if (!strcmp (buf, "digestion"))
269     pl->digestion = value;
270     else if (!strcmp (buf, "pickup"))
271     pl->mode = value;
272     else if (!strcmp (buf, "outputs_sync"))
273     pl->outputs_sync = value;
274     else if (!strcmp (buf, "outputs_count"))
275     pl->outputs_count = value;
276     else if (!strcmp (buf, "map"))
277     sscanf (bufall, "map %s", pl->maplevel);
278     else if (!strcmp (buf, "savebed_map"))
279     sscanf (bufall, "savebed_map %s", pl->savebed_map);
280     else if (!strcmp (buf, "bed_x"))
281     pl->bed_x = value;
282     else if (!strcmp (buf, "bed_y"))
283     pl->bed_y = value;
284     else if (!strcmp (buf, "weapon_sp"))
285     sscanf (buf, "weapon_sp %f", &pl->weapon_sp);
286     else if (!strcmp (buf, "Str"))
287     pl->orig_stats.Str = value;
288     else if (!strcmp (buf, "Dex"))
289     pl->orig_stats.Dex = value;
290     else if (!strcmp (buf, "Con"))
291     pl->orig_stats.Con = value;
292     else if (!strcmp (buf, "Int"))
293     pl->orig_stats.Int = value;
294     else if (!strcmp (buf, "Pow"))
295     pl->orig_stats.Pow = value;
296     else if (!strcmp (buf, "Wis"))
297     pl->orig_stats.Wis = value;
298     else if (!strcmp (buf, "Cha"))
299     pl->orig_stats.Cha = value;
300     else if (!strcmp (buf, "usekeys"))
301     {
302     if (!strcmp (bufall + 8, "key_inventory\n"))
303     pl->usekeys = key_inventory;
304     else if (!strcmp (bufall + 8, "keyrings\n"))
305     pl->usekeys = keyrings;
306     else if (!strcmp (bufall + 8, "containers\n"))
307     pl->usekeys = containers;
308     else
309     LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", bufall + 8);
310 root 1.6 }
311 root 1.15 else if (!strcmp (buf, "unapply"))
312     {
313     if (!strcmp (bufall + 8, "unapply_nochoice\n"))
314     pl->unapply = unapply_nochoice;
315     else if (!strcmp (bufall + 8, "unapply_never\n"))
316     pl->unapply = unapply_never;
317     else if (!strcmp (bufall + 8, "unapply_always\n"))
318     pl->unapply = unapply_always;
319     else
320     LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
321     }
322     else if (!strcmp (buf, "lev_array"))
323     {
324 root 1.30 for (int i = 1; i <= value; i++)
325 root 1.15 {
326     char line[128];
327    
328     fgets (line, 128, thawer);
329     pl->levhp[i] = atoi (line);
330     fgets (line, 128, thawer);
331     pl->levsp[i] = atoi (line);
332     fgets (line, 128, thawer);
333     pl->levgrace[i] = atoi (line);
334     }
335     /* spell_array code removed - don't know when that was last used.
336     * Even the load code below will someday be replaced by spells being
337     * objects.
338     */
339     }
340 root 1.30 else
341     LOG (llevDebug, "unparseable line in player file %s: %s\n", path, bufall);
342     }
343 root 1.15
344     /* this loads the standard objects values. */
345 root 1.30 load_object (thawer, pl->ob, 0);
346 root 1.15
347     /* If the map where the person was last saved does not exist,
348     * restart them on their home-savebed. This is good for when
349     * maps change between versions
350     * First, we check for partial path, then check to see if the full
351     * path (for unique player maps)
352     */
353 root 1.26 if (!has_been_loaded (pl->maplevel)
354     && check_path (pl->maplevel, 1) == -1
355     && check_path (pl->maplevel, 0) == -1)
356 root 1.15 {
357 root 1.26 strcpy (pl->maplevel, pl->savebed_map);
358 root 1.30 pl->ob->x = pl->bed_x, pl->ob->y = pl->bed_y;
359 elmex 1.1 }
360    
361 root 1.15 pl->last_save_tick = pticks;
362    
363 root 1.30 INVOKE_PLAYER (LOAD, pl, ARG_STRING (path));
364 root 1.15
365 root 1.30 return pl;
366     }
367 root 1.15