ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.25
Committed: Sat Dec 16 17:16:52 2006 UTC (17 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.24: +0 -3 lines
Log Message:
- remove no_shout
- serialise command execution somewhat again :(
- avoid exceptions

File Contents

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