ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.15
Committed: Sun Sep 10 15:59:27 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.14: +531 -460 lines
Log Message:
indent

File Contents

# User Rev Content
1 root 1.15
2 elmex 1.1 /*
3     * static char *rcsid_login_c =
4 root 1.15 * "$Id: login.C,v 1.14 2006-09-09 21:48:29 root Exp $";
5 elmex 1.1 */
6    
7     /*
8     CrossFire, A Multiplayer game for X-windows
9    
10     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11     Copyright (C) 1992 Frank Tore Johansen
12    
13     This program is free software; you can redistribute it and/or modify
14     it under the terms of the GNU General Public License as published by
15     the Free Software Foundation; either version 2 of the License, or
16     (at your option) any later version.
17    
18     This program is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21     GNU General Public License for more details.
22    
23     You should have received a copy of the GNU General Public License
24     along with this program; if not, write to the Free Software
25     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26    
27     The authors can be reached via e-mail at crossfire-devel@real-time.com
28     */
29    
30     #include <global.h>
31     #ifndef __CEXTRACT__
32 root 1.15 # include <sproto.h>
33 elmex 1.1 #endif
34     #include <spells.h>
35     #include <loader.h>
36     #include <define.h>
37    
38     extern void sub_weight (object *, signed long);
39     extern void add_weight (object *, signed long);
40     extern long pticks;
41    
42     /* If flag is non zero, it means that we want to try and save everyone, but
43     * keep the game running. Thus, we don't want to free any information.
44     */
45 root 1.15 void
46     emergency_save (int flag)
47     {
48 elmex 1.1 player *pl;
49 root 1.15
50 elmex 1.1 #ifndef NO_EMERGENCY_SAVE
51     trying_emergency_save = 1;
52 root 1.15 if (editor)
53 elmex 1.1 return;
54 root 1.15 LOG (llevError, "Emergency save: ");
55     for (pl = first_player; pl != NULL; pl = pl->next)
56     {
57     if (!pl->ob)
58     {
59     LOG (llevError, "No name, ignoring this.\n");
60     continue;
61     }
62     LOG (llevError, "%s ", pl->ob->name);
63     new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save...");
64 elmex 1.1
65     /* If we are not exiting the game (ie, this is sort of a backup save), then
66     * don't change the location back to the village. Note that there are other
67     * options to have backup saves be done at the starting village
68     */
69 root 1.15 if (!flag)
70     {
71     strcpy (pl->maplevel, first_map_path);
72     if (pl->ob->map != NULL)
73 root 1.6 pl->ob->map = NULL;
74 root 1.15 pl->ob->x = -1;
75     pl->ob->y = -1;
76     }
77     if (!save_player (pl->ob, flag))
78     {
79     LOG (llevError, "(failed) ");
80     new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save failed, checking score...");
81     }
82     check_score (pl->ob);
83 elmex 1.1 }
84 root 1.15 LOG (llevError, "\n");
85 elmex 1.1 #else
86 root 1.15 LOG (llevInfo, "Emergency saves disabled, no save attempted\n");
87 elmex 1.1 #endif
88     /* If the game is exiting, remove the player locks */
89 root 1.15 if (!flag)
90     {
91     for (pl = first_player; pl != NULL; pl = pl->next)
92     {
93     if (pl->ob)
94     {
95     }
96     }
97 elmex 1.1 }
98     }
99    
100     /* Delete character with name. if new is set, also delete the new
101     * style directory, otherwise, just delete the old style playfile
102     * (needed for transition)
103     */
104 root 1.15 void
105     delete_character (const char *name, int newchar)
106     {
107     char buf[MAX_BUF];
108 elmex 1.1
109 root 1.15 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
110     if (unlink (buf) == -1)
111     LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
112     if (newchar)
113     {
114     sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
115     /* this effectively does an rm -rf on the directory */
116     remove_directory (buf);
117 elmex 1.1 }
118     }
119    
120     /* This verify that a character of name exits, and that it matches
121     * password. It return 0 if there is match, 1 if no such player,
122     * 2 if incorrect password.
123     */
124    
125 root 1.15 int
126     verify_player (const char *name, char *password)
127 elmex 1.1 {
128 root 1.15 char buf[MAX_BUF];
129     int comp;
130     FILE *fp;
131    
132     if (strpbrk (name, "/.\\") != NULL)
133     {
134     LOG (llevError, "Username contains illegal characters: %s\n", name);
135     return 1;
136     }
137    
138     snprintf (buf, sizeof (buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
139     if (strlen (buf) >= sizeof (buf) - 1)
140     {
141     LOG (llevError, "Username too long: %s\n", name);
142     return 1;
143     }
144    
145     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
146     return 1;
147    
148     /* Read in the file until we find the password line. Our logic could
149     * be a bit better on cleaning up the password from the file, but since
150     * it is written by the program, I think it is fair to assume that the
151     * syntax should be pretty standard.
152     */
153     while (fgets (buf, MAX_BUF - 1, fp) != NULL)
154     {
155     if (!strncmp (buf, "password ", 9))
156     {
157     buf[strlen (buf) - 1] = 0; /* remove newline */
158     if (check_password (password, buf + 9))
159     {
160     close_and_delete (fp, comp);
161     return 0;
162 root 1.6 }
163 root 1.15 else
164     {
165     close_and_delete (fp, comp);
166     return 2;
167 root 1.6 }
168     }
169 elmex 1.1 }
170 root 1.15 LOG (llevDebug, "Could not find a password line in player %s\n", name);
171     close_and_delete (fp, comp);
172     return 1;
173 elmex 1.1 }
174    
175     /* Checks to see if anyone else by 'name' is currently playing.
176     * If we find that file or another character of some name is already in the
177     * game, we don't let this person join (we should really let the new player
178     * enter the password, and if correct, disconnect that socket and attach it to
179     * the players current session.
180     * If no one by that name is currently playing, we then make sure the name
181     * doesn't include any bogus characters.
182     * We return 0 if the name is in use/bad, 1 if it is OK to use this name.
183     */
184    
185 root 1.15 int
186     check_name (player *me, const char *name)
187     {
188     player *pl;
189 elmex 1.1
190 root 1.15 for (pl = first_player; pl != NULL; pl = pl->next)
191     if (pl != me && pl->ob->name != NULL && !strcmp (pl->ob->name, name))
192     {
193     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is already in use.");
194     return 0;
195     }
196 elmex 1.1
197 root 1.15 if (*name == '\0')
198     {
199     new_draw_info (NDI_UNIQUE, 0, me->ob, "Null names are not allowed.");
200     return 0;
201 elmex 1.1 }
202    
203 root 1.15 if (!playername_ok (name))
204     {
205     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name contains illegal characters.");
206     return 0;
207 elmex 1.1 }
208 root 1.15 if (strlen (name) >= MAX_NAME)
209     {
210     new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is too long.");
211     return 0;
212 elmex 1.1 }
213    
214 root 1.15 return 1;
215 elmex 1.1 }
216    
217 root 1.15 int
218     create_savedir_if_needed (char *savedir)
219 elmex 1.1 {
220     struct stat *buf;
221    
222 root 1.15 if ((buf = (struct stat *) malloc (sizeof (struct stat))) == NULL)
223     {
224     LOG (llevError, "Unable to save playerfile... out of memory.\n");
225     return 0;
226     }
227     else
228     {
229     stat (savedir, buf);
230     if (!S_ISDIR (buf->st_mode))
231     if (mkdir (savedir, SAVE_DIR_MODE))
232     {
233     LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno));
234     return 0;
235     }
236     free (buf);
237     }
238     return 1;
239 elmex 1.1 }
240    
241 root 1.15 void
242     destroy_object (object *op)
243 elmex 1.1 {
244 root 1.15 object *tmp;
245    
246     while ((tmp = op->inv))
247     destroy_object (tmp);
248 elmex 1.1
249 root 1.15 if (!QUERY_FLAG (op, FLAG_REMOVED))
250     remove_ob (op);
251     free_object (op);
252 elmex 1.1 }
253    
254     /*
255     * If flag is set, it's only backup, ie dont remove objects from inventory
256     * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player
257     * will be saved at the emergency save location.
258     * Returns non zero if successful.
259     */
260    
261 root 1.15 int
262     save_player (object *op, int flag)
263     {
264     object *tmp, *container = NULL;
265 elmex 1.1 player *pl = op->contr;
266 root 1.15 int i, wiz = QUERY_FLAG (op, FLAG_WIZ);
267    
268 elmex 1.1 #ifdef BACKUP_SAVE_AT_HOME
269     sint16 backup_x, backup_y;
270     #endif
271    
272 root 1.15 if (!op->stats.exp)
273     return 0; /* no experience, no save */
274 elmex 1.1
275 root 1.15 flag &= 1;
276 elmex 1.1
277 root 1.15 if (!pl->name_changed || (!flag && !op->stats.exp))
278     {
279     if (!flag)
280     {
281     new_draw_info (NDI_UNIQUE, 0, op, "Your game is not valid,");
282     new_draw_info (NDI_UNIQUE, 0, op, "Game not saved.");
283     }
284     return 0;
285 elmex 1.1 }
286 root 1.15
287     /* Sanity check - some stuff changes this when player is exiting */
288     if (op->type != PLAYER)
289 elmex 1.1 return 0;
290    
291 root 1.15 /* Prevent accidental saves if connection is reset after player has
292     * mostly exited.
293     */
294     if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
295     return 0;
296 elmex 1.1
297 root 1.9 INVOKE_PLAYER (SAVE, op->contr);
298 root 1.5
299 elmex 1.1 if (flag == 0)
300 root 1.15 terminate_all_pets (op);
301 elmex 1.1
302 root 1.9 object_freezer freezer;
303 root 1.3
304 root 1.9 /* Eneq(@csd.uu.se): If we have an open container hide it. */
305     if (op->container)
306 root 1.5 {
307 root 1.9 container = op->container;
308     op->container = NULL;
309 root 1.5 }
310 elmex 1.1
311 root 1.15 fprintf (freezer, "password %s\n", pl->password);
312 root 1.3
313 elmex 1.1 if (settings.set_title == TRUE)
314 root 1.15 if (pl->own_title[0] != '\0')
315     fprintf (freezer, "title %s\n", pl->own_title);
316 elmex 1.1
317 root 1.15 fprintf (freezer, "explore %d\n", pl->explore);
318     fprintf (freezer, "gen_hp %d\n", pl->gen_hp);
319     fprintf (freezer, "gen_sp %d\n", pl->gen_sp);
320     fprintf (freezer, "gen_grace %d\n", pl->gen_grace);
321     fprintf (freezer, "listening %d\n", pl->listening);
322     fprintf (freezer, "shoottype %d\n", pl->shoottype);
323     fprintf (freezer, "bowtype %d\n", pl->bowtype);
324     fprintf (freezer, "petmode %d\n", pl->petmode);
325     fprintf (freezer, "peaceful %d\n", pl->peaceful);
326     fprintf (freezer, "no_shout %d\n", pl->no_shout);
327     fprintf (freezer, "digestion %d\n", pl->digestion);
328     fprintf (freezer, "pickup %d\n", pl->mode);
329     fprintf (freezer, "outputs_sync %d\n", pl->outputs_sync);
330     fprintf (freezer, "outputs_count %d\n", pl->outputs_count);
331 elmex 1.1 /* Match the enumerations but in string form */
332 root 1.15 fprintf (freezer, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
333 elmex 1.1 /* Match the enumerations but in string form */
334 root 1.15 fprintf (freezer, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" :
335     (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
336 elmex 1.1
337     #ifdef BACKUP_SAVE_AT_HOME
338 root 1.15 if (op->map != NULL && flag == 0)
339 elmex 1.1 #else
340 root 1.15 if (op->map != NULL)
341 elmex 1.1 #endif
342 root 1.15 fprintf (freezer, "map %s\n", op->map->path);
343 elmex 1.1 else
344 root 1.15 fprintf (freezer, "map %s\n", settings.emergency_mapname);
345    
346     fprintf (freezer, "savebed_map %s\n", pl->savebed_map);
347     fprintf (freezer, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y);
348     fprintf (freezer, "weapon_sp %f\n", pl->weapon_sp);
349     fprintf (freezer, "Str %d\n", pl->orig_stats.Str);
350     fprintf (freezer, "Dex %d\n", pl->orig_stats.Dex);
351     fprintf (freezer, "Con %d\n", pl->orig_stats.Con);
352     fprintf (freezer, "Int %d\n", pl->orig_stats.Int);
353     fprintf (freezer, "Pow %d\n", pl->orig_stats.Pow);
354     fprintf (freezer, "Wis %d\n", pl->orig_stats.Wis);
355     fprintf (freezer, "Cha %d\n", pl->orig_stats.Cha);
356    
357     fprintf (freezer, "lev_array %d\n", op->level > 10 ? 10 : op->level);
358     for (i = 1; i <= pl->last_level && i <= 10; i++)
359     {
360     fprintf (freezer, "%d\n", pl->levhp[i]);
361     fprintf (freezer, "%d\n", pl->levsp[i]);
362     fprintf (freezer, "%d\n", pl->levgrace[i]);
363     }
364 root 1.4
365 root 1.9 freezer.put (op->contr);
366 root 1.4
367 root 1.15 fprintf (freezer, "endplst\n");
368 elmex 1.1
369 root 1.15 SET_FLAG (op, FLAG_NO_FIX_PLAYER);
370     CLEAR_FLAG (op, FLAG_WIZ);
371 elmex 1.1 #ifdef BACKUP_SAVE_AT_HOME
372 root 1.15 if (flag)
373     {
374     backup_x = op->x;
375     backup_y = op->y;
376     op->x = -1;
377     op->y = -1;
378     }
379 elmex 1.1 /* Save objects, but not unpaid objects. Don't remove objects from
380     * inventory.
381     */
382 root 1.15 save_object (freezer, op, 2);
383     if (flag)
384     {
385     op->x = backup_x;
386     op->y = backup_y;
387     }
388 elmex 1.1 #else
389 root 1.15 save_object (freezer, op, 3); /* don't check and don't remove */
390 elmex 1.1 #endif
391    
392 root 1.9 char filename[MAX_BUF];
393 root 1.15
394     sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
395     make_path_to_file (filename);
396 root 1.9 freezer.save (filename);
397    
398 root 1.15 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
399 elmex 1.1
400 root 1.15 if (!flag)
401     while ((tmp = op->inv))
402     destroy_object (tmp);
403 elmex 1.1
404     /* Eneq(@csd.uu.se): Reveal the container if we have one. */
405 root 1.15 if (flag && container != NULL)
406 elmex 1.1 op->container = container;
407    
408 root 1.15 if (wiz)
409     SET_FLAG (op, FLAG_WIZ);
410 root 1.5
411 root 1.15 if (!flag)
412     esrv_send_inventory (op, op);
413 elmex 1.1
414     return 1;
415     }
416    
417 root 1.15 void
418     check_login (object *op)
419     {
420     char filename[MAX_BUF];
421     char buf[MAX_BUF], bufall[MAX_BUF];
422     int i, value;
423     player *pl = op->contr;
424     int correct = 0;
425    
426     strcpy (pl->maplevel, first_map_path);
427     sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
428    
429     object_thawer thawer (filename);
430    
431     /* If no file, must be a new player, so lets get confirmation of
432     * the password. Return control to the higher level dispatch,
433     * since the rest of this just deals with loading of the file.
434     */
435     if (!thawer)
436     {
437     confirm_password (op);
438     return;
439 elmex 1.1 }
440 root 1.3
441 root 1.15 if (fgets (bufall, MAX_BUF, thawer) != NULL)
442     {
443     if (sscanf (bufall, "password %s\n", buf))
444     {
445     /* New password scheme: */
446     correct = check_password (pl->write_buf + 1, buf);
447 root 1.6 }
448 root 1.15 }
449     if (!correct)
450     {
451     new_draw_info (NDI_UNIQUE, 0, op, " ");
452     new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
453     new_draw_info (NDI_UNIQUE, 0, op, " ");
454     op->name = op->name_pl = "noname";
455     op->contr->socket.password_fails++;
456     if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
457     {
458     new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
459     LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
460     op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
461     }
462     else
463     get_name (op);
464     return; /* Once again, rest of code just loads the char */
465 elmex 1.1 }
466    
467     #ifdef SAVE_INTERVAL
468 root 1.15 pl->last_save_time = time (NULL);
469 elmex 1.1 #endif /* SAVE_INTERVAL */
470 root 1.15 pl->party = NULL;
471     if (settings.search_items == TRUE)
472     pl->search_str[0] = '\0';
473     pl->name_changed = 1;
474     pl->orig_stats.Str = 0;
475     pl->orig_stats.Dex = 0;
476     pl->orig_stats.Con = 0;
477     pl->orig_stats.Int = 0;
478     pl->orig_stats.Pow = 0;
479     pl->orig_stats.Wis = 0;
480     pl->orig_stats.Cha = 0;
481     strcpy (pl->savebed_map, first_map_path);
482     pl->bed_x = 0, pl->bed_y = 0;
483     pl->spellparam[0] = '\0';
484    
485     /* Loop through the file, loading the rest of the values */
486     while (fgets (bufall, MAX_BUF, thawer) != NULL)
487     {
488     sscanf (bufall, "%s %d\n", buf, &value);
489     if (!strcmp (buf, "endplst"))
490     break;
491     else if (!strcmp (buf, "oid"))
492     thawer.get (pl, value);
493     else if (!strcmp (buf, "title") && settings.set_title == TRUE)
494     sscanf (bufall, "title %[^\n]", pl->own_title);
495     else if (!strcmp (buf, "explore"))
496     pl->explore = value;
497     else if (!strcmp (buf, "gen_hp"))
498     pl->gen_hp = value;
499     else if (!strcmp (buf, "shoottype"))
500     pl->shoottype = (rangetype) value;
501     else if (!strcmp (buf, "bowtype"))
502     pl->bowtype = (bowtype_t) value;
503     else if (!strcmp (buf, "petmode"))
504     pl->petmode = (petmode_t) value;
505     else if (!strcmp (buf, "gen_sp"))
506     pl->gen_sp = value;
507     else if (!strcmp (buf, "gen_grace"))
508     pl->gen_grace = value;
509     else if (!strcmp (buf, "listening"))
510     pl->listening = value;
511     else if (!strcmp (buf, "peaceful"))
512     pl->peaceful = value;
513     else if (!strcmp (buf, "no_shout"))
514     pl->no_shout = value;
515     else if (!strcmp (buf, "digestion"))
516     pl->digestion = value;
517     else if (!strcmp (buf, "pickup"))
518     pl->mode = value;
519     else if (!strcmp (buf, "outputs_sync"))
520     pl->outputs_sync = value;
521     else if (!strcmp (buf, "outputs_count"))
522     pl->outputs_count = value;
523     else if (!strcmp (buf, "map"))
524     sscanf (bufall, "map %s", pl->maplevel);
525     else if (!strcmp (buf, "savebed_map"))
526     sscanf (bufall, "savebed_map %s", pl->savebed_map);
527     else if (!strcmp (buf, "bed_x"))
528     pl->bed_x = value;
529     else if (!strcmp (buf, "bed_y"))
530     pl->bed_y = value;
531     else if (!strcmp (buf, "weapon_sp"))
532     sscanf (buf, "weapon_sp %f", &pl->weapon_sp);
533     else if (!strcmp (buf, "Str"))
534     pl->orig_stats.Str = value;
535     else if (!strcmp (buf, "Dex"))
536     pl->orig_stats.Dex = value;
537     else if (!strcmp (buf, "Con"))
538     pl->orig_stats.Con = value;
539     else if (!strcmp (buf, "Int"))
540     pl->orig_stats.Int = value;
541     else if (!strcmp (buf, "Pow"))
542     pl->orig_stats.Pow = value;
543     else if (!strcmp (buf, "Wis"))
544     pl->orig_stats.Wis = value;
545     else if (!strcmp (buf, "Cha"))
546     pl->orig_stats.Cha = value;
547     else if (!strcmp (buf, "usekeys"))
548     {
549     if (!strcmp (bufall + 8, "key_inventory\n"))
550     pl->usekeys = key_inventory;
551     else if (!strcmp (bufall + 8, "keyrings\n"))
552     pl->usekeys = keyrings;
553     else if (!strcmp (bufall + 8, "containers\n"))
554     pl->usekeys = containers;
555     else
556     LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", bufall + 8);
557 root 1.6 }
558 root 1.15 else if (!strcmp (buf, "unapply"))
559     {
560     if (!strcmp (bufall + 8, "unapply_nochoice\n"))
561     pl->unapply = unapply_nochoice;
562     else if (!strcmp (bufall + 8, "unapply_never\n"))
563     pl->unapply = unapply_never;
564     else if (!strcmp (bufall + 8, "unapply_always\n"))
565     pl->unapply = unapply_always;
566     else
567     LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
568     }
569     else if (!strcmp (buf, "lev_array"))
570     {
571     for (i = 1; i <= value; i++)
572     {
573     char line[128];
574    
575     fgets (line, 128, thawer);
576     pl->levhp[i] = atoi (line);
577     fgets (line, 128, thawer);
578     pl->levsp[i] = atoi (line);
579     fgets (line, 128, thawer);
580     pl->levgrace[i] = atoi (line);
581     }
582     /* spell_array code removed - don't know when that was last used.
583     * Even the load code below will someday be replaced by spells being
584     * objects.
585     */
586     }
587     else if (!strcmp (buf, "known_spell"))
588     {
589     #if 0
590     /* Logic is left here in case someone wants to try
591     * and write code to update to spell objects.
592     */
593     char *cp = strchr (bufall, '\n');
594    
595     *cp = '\0';
596     cp = strchr (bufall, ' ');
597     cp++;
598     for (i = 0; i < NROFREALSPELLS; i++)
599     if (!strcmp (spells[i].name, cp))
600 root 1.11 {
601 root 1.15 pl->known_spells[pl->nrofknownspells++] = i;
602     break;
603 root 1.11 }
604 root 1.15 if (i == NROFREALSPELLS)
605     LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
606 elmex 1.1 #endif
607 root 1.6 }
608 root 1.15 } /* End of loop loading the character file */
609     leave_map (op);
610     op->speed = 0;
611     update_ob_speed (op);
612    
613     clear_object (op);
614    
615     op->contr = pl;
616     pl->ob = op;
617    
618     /* this loads the standard objects values. */
619     load_object (thawer, op, 0);
620    
621     CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
622    
623     strncpy (pl->title, op->arch->clone.name, sizeof (pl->title) - 1);
624     pl->title[sizeof (pl->title) - 1] = '\0';
625    
626     /* If the map where the person was last saved does not exist,
627     * restart them on their home-savebed. This is good for when
628     * maps change between versions
629     * First, we check for partial path, then check to see if the full
630     * path (for unique player maps)
631     */
632     if (check_path (pl->maplevel, 1) == -1)
633     {
634     if (check_path (pl->maplevel, 0) == -1)
635     {
636     strcpy (pl->maplevel, pl->savebed_map);
637     op->x = pl->bed_x, op->y = pl->bed_y;
638     }
639 elmex 1.1 }
640    
641 root 1.15 /* make sure he's a player--needed because of class change. */
642     op->type = PLAYER;
643 elmex 1.1
644 root 1.15 enter_exit (op, NULL);
645 elmex 1.1
646 root 1.15 pl->name_changed = 1;
647     pl->state = ST_PLAYING;
648 elmex 1.1 #ifdef AUTOSAVE
649 root 1.15 pl->last_save_tick = pticks;
650 elmex 1.1 #endif
651 root 1.15 op->carrying = sum_weight (op);
652     /* Need to call fix_player now - program modified so that it is not
653     * called during the load process (FLAG_NO_FIX_PLAYER set when
654     * saved)
655     * Moved ahead of the esrv functions, so proper weights will be
656     * sent to the client.
657     */
658     link_player_skills (op);
659    
660     if (!legal_range (op, op->contr->shoottype))
661     op->contr->shoottype = range_none;
662    
663     fix_player (op);
664    
665     /* if it's a dragon player, set the correct title here */
666     if (is_dragon_pl (op) && op->inv != NULL)
667     {
668     object *tmp, *abil = NULL, *skin = NULL;
669    
670     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
671     {
672     if (tmp->type == FORCE)
673     {
674     if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
675     abil = tmp;
676     else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
677     skin = tmp;
678 root 1.6 }
679     }
680 root 1.15 set_dragon_name (op, abil, skin);
681     }
682    
683     new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
684     new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
685    
686     INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename));
687     INVOKE_PLAYER (LOGIN, pl);
688    
689     op->contr->socket.update_look = 1;
690     /* If the player should be dead, call kill_player for them
691     * Only check for hp - if player lacks food, let the normal
692     * logic for that to take place. If player is permanently
693     * dead, and not using permadeath mode, the kill_player will
694     * set the play_again flag, so return.
695     */
696     if (op->stats.hp < 0)
697     {
698     new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
699     kill_player (op);
700     if (pl->state != ST_PLAYING)
701     return;
702 elmex 1.1 }
703 root 1.15 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
704    
705     /* Do this after checking for death - no reason sucking up bandwidth if
706     * the data isn't needed.
707     */
708     esrv_new_player (op->contr, op->weight + op->carrying);
709     esrv_send_inventory (op, op);
710     esrv_add_spells (op->contr, NULL);
711    
712     CLEAR_FLAG (op, FLAG_FRIENDLY);
713    
714     /* can_use_shield is a new flag. However, the can_use.. seems to largely come
715     * from the class, and not race. I don't see any way to get the class information
716     * to then update this. I don't think this will actually break anything - anyone
717     * that can use armour should be able to use a shield. What this may 'break'
718     * are features new characters get, eg, if someone starts up with a Q, they
719     * should be able to use a shield. However, old Q's won't get that advantage.
720     */
721     if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
722     SET_FLAG (op, FLAG_USE_SHIELD);
723     return;
724 elmex 1.1 }