ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.31
Committed: Sat Dec 23 03:38:43 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.30: +2 -4 lines
Log Message:
- surprisingly, there were some bugs. in Event, too :(
- dieing and food checking are now only done in ST_PLAYING state.
  this might, but should not be, exploitable, in serious ways.

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