ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.16
Committed: Sun Sep 10 16:56:22 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.15: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1
2 /*
3 * static char *rcsid_login_c =
4 * "$Id: login.C,v 1.15 2006-09-10 15:59:27 root Exp $";
5 */
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 # include <sproto.h>
33 #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 void
46 emergency_save (int flag)
47 {
48 player *pl;
49
50 #ifndef NO_EMERGENCY_SAVE
51 trying_emergency_save = 1;
52 if (editor)
53 return;
54 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
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 if (!flag)
70 {
71 strcpy (pl->maplevel, first_map_path);
72 if (pl->ob->map != NULL)
73 pl->ob->map = NULL;
74 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 }
84 LOG (llevError, "\n");
85 #else
86 LOG (llevInfo, "Emergency saves disabled, no save attempted\n");
87 #endif
88 /* If the game is exiting, remove the player locks */
89 if (!flag)
90 {
91 for (pl = first_player; pl != NULL; pl = pl->next)
92 {
93 if (pl->ob)
94 {
95 }
96 }
97 }
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 void
105 delete_character (const char *name, int newchar)
106 {
107 char buf[MAX_BUF];
108
109 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 }
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 int
126 verify_player (const char *name, char *password)
127 {
128 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 }
163 else
164 {
165 close_and_delete (fp, comp);
166 return 2;
167 }
168 }
169 }
170 LOG (llevDebug, "Could not find a password line in player %s\n", name);
171 close_and_delete (fp, comp);
172 return 1;
173 }
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 int
186 check_name (player *me, const char *name)
187 {
188 player *pl;
189
190 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
197 if (*name == '\0')
198 {
199 new_draw_info (NDI_UNIQUE, 0, me->ob, "Null names are not allowed.");
200 return 0;
201 }
202
203 if (!playername_ok (name))
204 {
205 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name contains illegal characters.");
206 return 0;
207 }
208 if (strlen (name) >= MAX_NAME)
209 {
210 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is too long.");
211 return 0;
212 }
213
214 return 1;
215 }
216
217 int
218 create_savedir_if_needed (char *savedir)
219 {
220 struct stat *buf;
221
222 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 }
240
241 void
242 destroy_object (object *op)
243 {
244 object *tmp;
245
246 while ((tmp = op->inv))
247 destroy_object (tmp);
248
249 if (!QUERY_FLAG (op, FLAG_REMOVED))
250 remove_ob (op);
251 free_object (op);
252 }
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 int
262 save_player (object *op, int flag)
263 {
264 object *tmp, *container = NULL;
265 player *pl = op->contr;
266 int i, wiz = QUERY_FLAG (op, FLAG_WIZ);
267
268 #ifdef BACKUP_SAVE_AT_HOME
269 sint16 backup_x, backup_y;
270 #endif
271
272 if (!op->stats.exp)
273 return 0; /* no experience, no save */
274
275 flag &= 1;
276
277 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 }
286
287 /* Sanity check - some stuff changes this when player is exiting */
288 if (op->type != PLAYER)
289 return 0;
290
291 /* 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
297 INVOKE_PLAYER (SAVE, op->contr);
298
299 if (flag == 0)
300 terminate_all_pets (op);
301
302 object_freezer freezer;
303
304 /* Eneq(@csd.uu.se): If we have an open container hide it. */
305 if (op->container)
306 {
307 container = op->container;
308 op->container = NULL;
309 }
310
311 fprintf (freezer, "password %s\n", pl->password);
312
313 if (settings.set_title == TRUE)
314 if (pl->own_title[0] != '\0')
315 fprintf (freezer, "title %s\n", pl->own_title);
316
317 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 /* Match the enumerations but in string form */
332 fprintf (freezer, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
333 /* Match the enumerations but in string form */
334 fprintf (freezer, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" :
335 (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
336
337 #ifdef BACKUP_SAVE_AT_HOME
338 if (op->map != NULL && flag == 0)
339 #else
340 if (op->map != NULL)
341 #endif
342 fprintf (freezer, "map %s\n", op->map->path);
343 else
344 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
365 freezer.put (op->contr);
366
367 fprintf (freezer, "endplst\n");
368
369 SET_FLAG (op, FLAG_NO_FIX_PLAYER);
370 CLEAR_FLAG (op, FLAG_WIZ);
371 #ifdef BACKUP_SAVE_AT_HOME
372 if (flag)
373 {
374 backup_x = op->x;
375 backup_y = op->y;
376 op->x = -1;
377 op->y = -1;
378 }
379 /* Save objects, but not unpaid objects. Don't remove objects from
380 * inventory.
381 */
382 save_object (freezer, op, 2);
383 if (flag)
384 {
385 op->x = backup_x;
386 op->y = backup_y;
387 }
388 #else
389 save_object (freezer, op, 3); /* don't check and don't remove */
390 #endif
391
392 char filename[MAX_BUF];
393
394 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
395 make_path_to_file (filename);
396 freezer.save (filename);
397
398 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
399
400 if (!flag)
401 while ((tmp = op->inv))
402 destroy_object (tmp);
403
404 /* Eneq(@csd.uu.se): Reveal the container if we have one. */
405 if (flag && container != NULL)
406 op->container = container;
407
408 if (wiz)
409 SET_FLAG (op, FLAG_WIZ);
410
411 if (!flag)
412 esrv_send_inventory (op, op);
413
414 return 1;
415 }
416
417 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 }
440
441 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 }
448 }
449
450 if (!correct)
451 {
452 new_draw_info (NDI_UNIQUE, 0, op, " ");
453 new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
454 new_draw_info (NDI_UNIQUE, 0, op, " ");
455 op->name = op->name_pl = "noname";
456 op->contr->socket.password_fails++;
457 if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
458 {
459 new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
460 LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
461 op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
462 }
463 else
464 get_name (op);
465 return; /* Once again, rest of code just loads the char */
466 }
467
468 #ifdef SAVE_INTERVAL
469 pl->last_save_time = time (NULL);
470 #endif /* SAVE_INTERVAL */
471 pl->party = NULL;
472 if (settings.search_items == TRUE)
473 pl->search_str[0] = '\0';
474 pl->name_changed = 1;
475 pl->orig_stats.Str = 0;
476 pl->orig_stats.Dex = 0;
477 pl->orig_stats.Con = 0;
478 pl->orig_stats.Int = 0;
479 pl->orig_stats.Pow = 0;
480 pl->orig_stats.Wis = 0;
481 pl->orig_stats.Cha = 0;
482 strcpy (pl->savebed_map, first_map_path);
483 pl->bed_x = 0, pl->bed_y = 0;
484 pl->spellparam[0] = '\0';
485
486 /* Loop through the file, loading the rest of the values */
487 while (fgets (bufall, MAX_BUF, thawer) != NULL)
488 {
489 sscanf (bufall, "%s %d\n", buf, &value);
490 if (!strcmp (buf, "endplst"))
491 break;
492 else if (!strcmp (buf, "oid"))
493 thawer.get (pl, value);
494 else if (!strcmp (buf, "title") && settings.set_title == TRUE)
495 sscanf (bufall, "title %[^\n]", pl->own_title);
496 else if (!strcmp (buf, "explore"))
497 pl->explore = value;
498 else if (!strcmp (buf, "gen_hp"))
499 pl->gen_hp = value;
500 else if (!strcmp (buf, "shoottype"))
501 pl->shoottype = (rangetype) value;
502 else if (!strcmp (buf, "bowtype"))
503 pl->bowtype = (bowtype_t) value;
504 else if (!strcmp (buf, "petmode"))
505 pl->petmode = (petmode_t) value;
506 else if (!strcmp (buf, "gen_sp"))
507 pl->gen_sp = value;
508 else if (!strcmp (buf, "gen_grace"))
509 pl->gen_grace = value;
510 else if (!strcmp (buf, "listening"))
511 pl->listening = value;
512 else if (!strcmp (buf, "peaceful"))
513 pl->peaceful = value;
514 else if (!strcmp (buf, "no_shout"))
515 pl->no_shout = value;
516 else if (!strcmp (buf, "digestion"))
517 pl->digestion = value;
518 else if (!strcmp (buf, "pickup"))
519 pl->mode = value;
520 else if (!strcmp (buf, "outputs_sync"))
521 pl->outputs_sync = value;
522 else if (!strcmp (buf, "outputs_count"))
523 pl->outputs_count = value;
524 else if (!strcmp (buf, "map"))
525 sscanf (bufall, "map %s", pl->maplevel);
526 else if (!strcmp (buf, "savebed_map"))
527 sscanf (bufall, "savebed_map %s", pl->savebed_map);
528 else if (!strcmp (buf, "bed_x"))
529 pl->bed_x = value;
530 else if (!strcmp (buf, "bed_y"))
531 pl->bed_y = value;
532 else if (!strcmp (buf, "weapon_sp"))
533 sscanf (buf, "weapon_sp %f", &pl->weapon_sp);
534 else if (!strcmp (buf, "Str"))
535 pl->orig_stats.Str = value;
536 else if (!strcmp (buf, "Dex"))
537 pl->orig_stats.Dex = value;
538 else if (!strcmp (buf, "Con"))
539 pl->orig_stats.Con = value;
540 else if (!strcmp (buf, "Int"))
541 pl->orig_stats.Int = value;
542 else if (!strcmp (buf, "Pow"))
543 pl->orig_stats.Pow = value;
544 else if (!strcmp (buf, "Wis"))
545 pl->orig_stats.Wis = value;
546 else if (!strcmp (buf, "Cha"))
547 pl->orig_stats.Cha = value;
548 else if (!strcmp (buf, "usekeys"))
549 {
550 if (!strcmp (bufall + 8, "key_inventory\n"))
551 pl->usekeys = key_inventory;
552 else if (!strcmp (bufall + 8, "keyrings\n"))
553 pl->usekeys = keyrings;
554 else if (!strcmp (bufall + 8, "containers\n"))
555 pl->usekeys = containers;
556 else
557 LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", bufall + 8);
558 }
559 else if (!strcmp (buf, "unapply"))
560 {
561 if (!strcmp (bufall + 8, "unapply_nochoice\n"))
562 pl->unapply = unapply_nochoice;
563 else if (!strcmp (bufall + 8, "unapply_never\n"))
564 pl->unapply = unapply_never;
565 else if (!strcmp (bufall + 8, "unapply_always\n"))
566 pl->unapply = unapply_always;
567 else
568 LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
569 }
570 else if (!strcmp (buf, "lev_array"))
571 {
572 for (i = 1; i <= value; i++)
573 {
574 char line[128];
575
576 fgets (line, 128, thawer);
577 pl->levhp[i] = atoi (line);
578 fgets (line, 128, thawer);
579 pl->levsp[i] = atoi (line);
580 fgets (line, 128, thawer);
581 pl->levgrace[i] = atoi (line);
582 }
583 /* spell_array code removed - don't know when that was last used.
584 * Even the load code below will someday be replaced by spells being
585 * objects.
586 */
587 }
588 else if (!strcmp (buf, "known_spell"))
589 {
590 #if 0
591 /* Logic is left here in case someone wants to try
592 * and write code to update to spell objects.
593 */
594 char *cp = strchr (bufall, '\n');
595
596 *cp = '\0';
597 cp = strchr (bufall, ' ');
598 cp++;
599 for (i = 0; i < NROFREALSPELLS; i++)
600 if (!strcmp (spells[i].name, cp))
601 {
602 pl->known_spells[pl->nrofknownspells++] = i;
603 break;
604 }
605 if (i == NROFREALSPELLS)
606 LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
607 #endif
608 }
609 } /* End of loop loading the character file */
610 leave_map (op);
611 op->speed = 0;
612 update_ob_speed (op);
613
614 clear_object (op);
615
616 op->contr = pl;
617 pl->ob = op;
618
619 /* this loads the standard objects values. */
620 load_object (thawer, op, 0);
621
622 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
623
624 strncpy (pl->title, op->arch->clone.name, sizeof (pl->title) - 1);
625 pl->title[sizeof (pl->title) - 1] = '\0';
626
627 /* If the map where the person was last saved does not exist,
628 * restart them on their home-savebed. This is good for when
629 * maps change between versions
630 * First, we check for partial path, then check to see if the full
631 * path (for unique player maps)
632 */
633 if (check_path (pl->maplevel, 1) == -1)
634 {
635 if (check_path (pl->maplevel, 0) == -1)
636 {
637 strcpy (pl->maplevel, pl->savebed_map);
638 op->x = pl->bed_x, op->y = pl->bed_y;
639 }
640 }
641
642 /* make sure he's a player--needed because of class change. */
643 op->type = PLAYER;
644
645 enter_exit (op, NULL);
646
647 pl->name_changed = 1;
648 pl->state = ST_PLAYING;
649 #ifdef AUTOSAVE
650 pl->last_save_tick = pticks;
651 #endif
652 op->carrying = sum_weight (op);
653 /* Need to call fix_player now - program modified so that it is not
654 * called during the load process (FLAG_NO_FIX_PLAYER set when
655 * saved)
656 * Moved ahead of the esrv functions, so proper weights will be
657 * sent to the client.
658 */
659 link_player_skills (op);
660
661 if (!legal_range (op, op->contr->shoottype))
662 op->contr->shoottype = range_none;
663
664 fix_player (op);
665
666 /* if it's a dragon player, set the correct title here */
667 if (is_dragon_pl (op) && op->inv != NULL)
668 {
669 object *tmp, *abil = NULL, *skin = NULL;
670
671 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
672 {
673 if (tmp->type == FORCE)
674 {
675 if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
676 abil = tmp;
677 else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
678 skin = tmp;
679 }
680 }
681 set_dragon_name (op, abil, skin);
682 }
683
684 new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
685 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
686
687 INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename));
688 INVOKE_PLAYER (LOGIN, pl);
689
690 op->contr->socket.update_look = 1;
691 /* If the player should be dead, call kill_player for them
692 * Only check for hp - if player lacks food, let the normal
693 * logic for that to take place. If player is permanently
694 * dead, and not using permadeath mode, the kill_player will
695 * set the play_again flag, so return.
696 */
697 if (op->stats.hp < 0)
698 {
699 new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
700 kill_player (op);
701 if (pl->state != ST_PLAYING)
702 return;
703 }
704 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
705
706 /* Do this after checking for death - no reason sucking up bandwidth if
707 * the data isn't needed.
708 */
709 esrv_new_player (op->contr, op->weight + op->carrying);
710 esrv_send_inventory (op, op);
711 esrv_add_spells (op->contr, NULL);
712
713 CLEAR_FLAG (op, FLAG_FRIENDLY);
714
715 /* can_use_shield is a new flag. However, the can_use.. seems to largely come
716 * from the class, and not race. I don't see any way to get the class information
717 * to then update this. I don't think this will actually break anything - anyone
718 * that can use armour should be able to use a shield. What this may 'break'
719 * are features new characters get, eg, if someone starts up with a Q, they
720 * should be able to use a shield. However, old Q's won't get that advantage.
721 */
722 if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
723 SET_FLAG (op, FLAG_USE_SHIELD);
724 return;
725 }