Crossfire Server, Branches 1.12  R18729
login.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_login_c =
3  * "$Id: login.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
34 #include <global.h>
35 #ifndef __CEXTRACT__
36 #include <sproto.h>
37 #endif
38 #include <spells.h>
39 #include <loader.h>
40 #include <define.h>
41 
42 static void copy_file(const char *filename, FILE *fpout);
43 
51 void emergency_save(int flag) {
52 #ifndef NO_EMERGENCY_SAVE
53  player *pl;
54 
56  LOG(llevError, "Emergency save: ");
57  for (pl = first_player; pl != NULL; pl = pl->next) {
58  if (!pl->ob) {
59  LOG(llevError, "No name, ignoring this.\n");
60  continue;
61  }
62  LOG(llevError, "%s ", pl->ob->name);
64  "Emergency save...", NULL);
65 
66  /* If we are not exiting the game (ie, this is sort of a backup save), then
67  * don't change the location back to the village. Note that there are other
68  * options to have backup saves be done at the starting village
69  */
70  if (!flag) {
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  LOG(llevError, "(failed) ");
80  "Emergency save failed, checking score...", NULL);
81  }
82  check_score(pl->ob, 1);
83  }
84  LOG(llevError, "\n");
85 #else
86  LOG(llevInfo, "Emergency saves disabled, no save attempted\n");
87 #endif
88 }
89 
97 void delete_character(const char *name) {
98  char buf[MAX_BUF];
99 
100  snprintf(buf, sizeof(buf), "%s/%s/%s", settings.localdir, settings.playerdir, name);
101  /* this effectively does an rm -rf on the directory */
102  remove_directory(buf);
103 }
104 
120 int verify_player(const char *name, char *password) {
121  char buf[MAX_BUF];
122  int comp;
123  FILE *fp;
124 
125  if (strpbrk(name, "/.\\") != NULL) {
126  LOG(llevError, "Username contains illegal characters: %s\n", name);
127  return 1;
128  }
129 
130  snprintf(buf, sizeof(buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
131  if (strlen(buf) >= sizeof(buf)-1) {
132  LOG(llevError, "Username too long: %s\n", name);
133  return 1;
134  }
135 
136  if ((fp = open_and_uncompress(buf, 0, &comp)) == NULL)
137  return 1;
138 
139  /* Read in the file until we find the password line. Our logic could
140  * be a bit better on cleaning up the password from the file, but since
141  * it is written by the program, I think it is fair to assume that the
142  * syntax should be pretty standard.
143  */
144  while (fgets(buf, MAX_BUF-1, fp) != NULL) {
145  if (!strncmp(buf, "password ", 9)) {
146  buf[strlen(buf)-1] = 0; /* remove newline */
147  if (check_password(password, buf+9)) {
148  close_and_delete(fp, comp);
149  return 0;
150  } else {
151  close_and_delete(fp, comp);
152  return 2;
153  }
154  }
155  }
156  LOG(llevDebug, "Could not find a password line in player %s\n", name);
157  close_and_delete(fp, comp);
158  return 1;
159 }
160 
173 int check_name(player *me, const char *name) {
174  if (*name == '\0') {
176  "Your username cannot be blank.", NULL);
177  return 0;
178  }
179 
180  if (!playername_ok(name)) {
182  "That name contains illegal characters. Use letters, hyphens and underscores only. Hyphens and underscores are not allowed as the first character.", NULL);
183  return 0;
184  }
185  if (strlen(name) >= MAX_NAME) {
187  "That name is too long. (Max length: %d characters)", NULL, MAX_NAME);
188  return 0;
189  }
190 
191  return 1;
192 }
193 
201 void destroy_object(object *op) {
202  object *tmp;
203  while ((tmp = op->inv))
204  destroy_object(tmp);
205 
206  if (!QUERY_FLAG(op, FLAG_REMOVED))
207  remove_ob(op);
208  free_object(op);
209 }
210 
223 int save_player(object *op, int flag) {
224  FILE *fp;
225  char filename[MAX_BUF], *tmpfilename, backupfile[MAX_BUF];
226  object *tmp, *container = NULL;
227  player *pl = op->contr;
228  int i, wiz = QUERY_FLAG(op, FLAG_WIZ);
229  long checksum;
230 #ifdef BACKUP_SAVE_AT_HOME
231  sint16 backup_x, backup_y;
232 #endif
233 
234  if (!op->stats.exp)
235  return 0; /* no experience, no save */
236 
237  flag &= 1;
238 
239  if (!pl->name_changed||(!flag&&!op->stats.exp)) {
240  if (!flag) {
242  "Your game is not valid, game not saved.", NULL);
243  }
244  return 0;
245  }
246 
247  /* Sanity check - some stuff changes this when player is exiting */
248  if (op->type != PLAYER)
249  return 0;
250 
251  /* Prevent accidental saves if connection is reset after player has
252  * mostly exited.
253  */
254  if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
255  return 0;
256 
257  if (flag == 0)
258  terminate_all_pets(op);
259 
260  snprintf(filename, sizeof(filename), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, op->name, op->name);
261  make_path_to_file(filename);
262  fp = tempnam_secure(settings.tmpdir, NULL, &tmpfilename);
263  if (!fp) {
265  "Can't get secure temporary file for save.", NULL);
266  LOG(llevDebug, "Can't get secure temporary file for save.\n");
267  return 0;
268  }
269 
270  /* Eneq(@csd.uu.se): If we have an open container hide it. */
271  if (op->container) {
272  container = op->container;
273  op->container = NULL;
274  }
275 
276  fprintf(fp, "password %s\n", pl->password);
277  if (settings.set_title == TRUE)
278  if (pl->own_title[0] != '\0')
279  fprintf(fp, "title %s\n", pl->own_title);
280 
281  fprintf(fp, "explore %d\n", pl->explore);
282  fprintf(fp, "gen_hp %d\n", pl->gen_hp);
283  fprintf(fp, "gen_sp %d\n", pl->gen_sp);
284  fprintf(fp, "gen_grace %d\n", pl->gen_grace);
285  fprintf(fp, "listening %d\n", pl->listening);
286  fprintf(fp, "shoottype %d\n", pl->shoottype);
287  fprintf(fp, "bowtype %d\n", pl->bowtype);
288  fprintf(fp, "petmode %d\n", pl->petmode);
289  fprintf(fp, "peaceful %d\n", pl->peaceful);
290  fprintf(fp, "no_shout %d\n", pl->no_shout);
291  fprintf(fp, "digestion %d\n", pl->digestion);
292  fprintf(fp, "pickup %u\n", pl->mode);
293  fprintf(fp, "outputs_sync %d\n", pl->outputs_sync);
294  fprintf(fp, "outputs_count %d\n", pl->outputs_count);
295  /* Match the enumerations but in string form */
296  fprintf(fp, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
297  /* Match the enumerations but in string form */
298  fprintf(fp, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" : (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
299 
300 #ifdef BACKUP_SAVE_AT_HOME
301  if (op->map != NULL && flag == 0)
302 #else
303  if (op->map != NULL)
304 #endif
305  fprintf(fp, "map %s\n", op->map->path);
306  else
307  fprintf(fp, "map %s\n", settings.emergency_mapname);
308 
309  fprintf(fp, "savebed_map %s\n", pl->savebed_map);
310  fprintf(fp, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y);
311  fprintf(fp, "weapon_sp %f\n", pl->weapon_sp);
312  fprintf(fp, "Str %d\n", pl->orig_stats.Str);
313  fprintf(fp, "Dex %d\n", pl->orig_stats.Dex);
314  fprintf(fp, "Con %d\n", pl->orig_stats.Con);
315  fprintf(fp, "Int %d\n", pl->orig_stats.Int);
316  fprintf(fp, "Pow %d\n", pl->orig_stats.Pow);
317  fprintf(fp, "Wis %d\n", pl->orig_stats.Wis);
318  fprintf(fp, "Cha %d\n", pl->orig_stats.Cha);
319 
320  fprintf(fp, "lev_array %d\n", MIN(op->level, 10));
321  for (i = 1; i <= pl->last_level && i <= 10; i++) {
322  fprintf(fp, "%d\n", pl->levhp[i]);
323  fprintf(fp, "%d\n", pl->levsp[i]);
324  fprintf(fp, "%d\n", pl->levgrace[i]);
325  }
326  fprintf(fp, "party_rejoin_mode %d\n", pl->rejoin_party);
327  if (pl->party != NULL) {
328  fprintf(fp, "party_rejoin_name %s\n", pl->party->partyname);
329  fprintf(fp, "party_rejoin_password %s\n", pl->party->passwd);
330  }
331  fprintf(fp, "language %d\n", pl->language);
332  fprintf(fp, "endplst\n");
333 
335  CLEAR_FLAG(op, FLAG_WIZ);
336 #ifdef BACKUP_SAVE_AT_HOME
337  if (flag) {
338  backup_x = op->x;
339  backup_y = op->y;
340  op->x = -1;
341  op->y = -1;
342  }
343  /* Save objects, but not unpaid objects. Don't remove objects from
344  * inventory.
345  */
346  i = save_object(fp, op, SAVE_FLAG_NO_REMOVE);
347  if (flag) {
348  op->x = backup_x;
349  op->y = backup_y;
350  }
351 #else
352  i = save_object(fp, op, SAVE_FLAG_SAVE_UNPAID|SAVE_FLAG_NO_REMOVE); /* don't check and don't remove */
353 #endif
354 
355  if (wiz)
356  SET_FLAG(op, FLAG_WIZ);
357 
358  if (fclose(fp) != 0 || i != SAVE_ERROR_OK) { /* make sure the write succeeded */
360  "Can't save character!", NULL);
361  draw_ext_info_format(NDI_ALL_DMS|NDI_RED, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "Save failure for player %s!", NULL, op->name);
362  unlink(tmpfilename);
363  free(tmpfilename);
364  return 0;
365  }
366 
368 
369  if (!flag) {
370  while ((tmp = op->inv))
371  destroy_object(tmp);
372 
373  /* destroying objects will most likely destroy the pointer
374  * in op->contr->ranges[], so clear the range to a safe value.
375  */
376  op->contr->shoottype = range_none;
377  }
378 
379  checksum = 0;
380  snprintf(backupfile, sizeof(backupfile), "%s.tmp", filename);
381  rename(filename, backupfile);
382  fp = fopen(filename, "w");
383  if (!fp) {
385  "Can't open file for save.", NULL);
386  unlink(tmpfilename);
387  free(tmpfilename);
388  return 0;
389  }
390  fprintf(fp, "checksum %lx\n", checksum);
391  copy_file(tmpfilename, fp);
392  unlink(tmpfilename);
393  free(tmpfilename);
394  if (fclose(fp) == EOF) { /* got write error */
396  "Can't close file for save.", NULL);
397  rename(backupfile, filename); /* Restore the original */
398  return 0;
399  } else
400  unlink(backupfile);
401 
402  /* Eneq(@csd.uu.se): Reveal the container if we have one. */
403  if (flag && container != NULL)
404  op->container = container;
405 
406  if (!flag)
407  esrv_send_inventory(op, op);
408 
409  chmod(filename, SAVE_MODE);
410  return 1;
411 }
412 
421 static void copy_file(const char *filename, FILE *fpout) {
422  FILE *fp;
423  char buf[MAX_BUF];
424 
425  if ((fp = fopen(filename, "r")) == NULL) {
426  LOG(llevError, "copy_file failed to open \"%s\", player file(s) may be corrupt.\n", filename);
427  return;
428  }
429  while (fgets(buf, MAX_BUF, fp) != NULL)
430  fputs(buf, fpout);
431  fclose(fp);
432 }
433 
441 static void wrong_password(object *op) {
443  "\nA character with this name already exists. "
444  "Please choose another name, or make sure you entered your "
445  "password correctly.\n",
446  NULL);
447 
448  FREE_AND_COPY(op->name, "noname");
449  FREE_AND_COPY(op->name_pl, "noname");
450 
451  op->contr->socket.password_fails++;
454  "You gave an incorrect password too many times, "
455  "you will now be dropped from the server.",
456  NULL);
457 
458  LOG(llevInfo, "A player connecting from %s has been dropped for password failure\n",
459  op->contr->socket.host);
460 
461  op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
462  } else
463  get_name(op);
464 }
465 
473 void check_login(object *op) {
474  FILE *fp;
475  char filename[MAX_BUF];
476  char buf[MAX_BUF], bufall[MAX_BUF];
477  int i, value, comp;
478  long checksum = 0;
479  player *pl = op->contr, *pltmp;
480  int correct = 0;
481  time_t elapsed_save_time = 0;
482  struct stat statbuf;
483  char *party_name = NULL, party_password[9];
484 
485  strcpy(pl->maplevel, first_map_path);
486  party_password[0] = 0;
487 
488  /* Check if this matches a connected player, and if yes disconnect old / connect new. */
489  for (pltmp = first_player; pltmp != NULL; pltmp = pltmp->next) {
490  if (pltmp != pl && pltmp->ob->name != NULL && !strcmp(pltmp->ob->name, op->name)) {
491  if (check_password(pl->write_buf+1, pltmp->password)) {
492 
493  /* We could try and be more clever and re-assign the existing
494  * object to the new player, etc. However, I'm concerned that
495  * there may be a lot of other state that still needs to be sent
496  * in that case (we can't make any assumptions on what the
497  * client knows, as maybe the client crashed), so treating it
498  * as just a normal login is the safest and easiest thing to do.
499  */
500 
501  pltmp->socket.status = Ns_Dead;
502 
503  save_player(pltmp->ob, 0);
504  if (!QUERY_FLAG(pltmp->ob, FLAG_REMOVED)) {
505  /* Need to terminate the pets, since the new object
506  * will be different
507  */
508  terminate_all_pets(pltmp->ob);
509  remove_ob(pltmp->ob);
510  }
511  leave(pltmp, 1);
512  final_free_player(pltmp);
513  break;
514  } else {
515  wrong_password(op);
516  return;
517  }
518  }
519  }
520 
521  snprintf(filename, sizeof(filename), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, op->name, op->name);
522 
523  /* If no file, must be a new player, so lets get confirmation of
524  * the password. Return control to the higher level dispatch,
525  * since the rest of this just deals with loading of the file.
526  */
527  if ((fp = open_and_uncompress(filename, 1, &comp)) == NULL) {
528  confirm_password(op);
529  return;
530  }
531  if (fstat(fileno(fp), &statbuf)) {
532  LOG(llevError, "Unable to stat %s?\n", filename);
533  elapsed_save_time = 0;
534  } else {
535  elapsed_save_time = time(NULL)-statbuf.st_mtime;
536  if (elapsed_save_time < 0) {
537  LOG(llevError, "Player file %s was saved in the future? (%d time)\n", filename, elapsed_save_time);
538  elapsed_save_time = 0;
539  }
540  }
541 
542  if (fgets(bufall, MAX_BUF, fp) != NULL) {
543  if (!strncmp(bufall, "checksum ", 9)) {
544  checksum = strtol(bufall+9, (char **)NULL, 16);
545  (void)fgets(bufall, MAX_BUF, fp);
546  }
547  if (sscanf(bufall, "password %s\n", buf)) {
548  /* New password scheme: */
549  correct = check_password(pl->write_buf+1, buf);
550  }
551  /* Old password mode removed - I have no idea what it
552  * was, and the current password mechanism has been used
553  * for at least several years.
554  */
555  }
556  if (!correct) {
557  wrong_password(op);
558  fclose(fp);
559  return;
560  }
561 
562 #ifdef SAVE_INTERVAL
563  pl->last_save_time = time(NULL);
564 #endif /* SAVE_INTERVAL */
565  pl->party = NULL;
566  if (settings.search_items == TRUE)
567  pl->search_str[0] = '\0';
568  pl->name_changed = 1;
569  pl->orig_stats.Str = 0;
570  pl->orig_stats.Dex = 0;
571  pl->orig_stats.Con = 0;
572  pl->orig_stats.Int = 0;
573  pl->orig_stats.Pow = 0;
574  pl->orig_stats.Wis = 0;
575  pl->orig_stats.Cha = 0;
576  strcpy(pl->savebed_map, first_map_path);
577  pl->bed_x = 0,
578  pl->bed_y = 0;
579  pl->spellparam[0] = '\0';
580 
581  /* Loop through the file, loading the rest of the values */
582  while (fgets(bufall, MAX_BUF, fp) != NULL) {
583  sscanf(bufall, "%s %d\n", buf, &value);
584  if (!strcmp(buf, "endplst"))
585  break;
586  else if (!strcmp(buf, "title") && settings.set_title == TRUE)
587  sscanf(bufall, "title %[^\n]", pl->own_title);
588  else if (!strcmp(buf, "explore"))
589  pl->explore = value;
590  else if (!strcmp(buf, "gen_hp"))
591  pl->gen_hp = value;
592  else if (!strcmp(buf, "shoottype"))
593  pl->shoottype = (rangetype)value;
594  else if (!strcmp(buf, "bowtype"))
595  pl->bowtype = (bowtype_t)value;
596  else if (!strcmp(buf, "petmode"))
597  pl->petmode = (petmode_t)value;
598  else if (!strcmp(buf, "gen_sp"))
599  pl->gen_sp = value;
600  else if (!strcmp(buf, "gen_grace"))
601  pl->gen_grace = value;
602  else if (!strcmp(buf, "listening"))
603  pl->listening = value;
604  else if (!strcmp(buf, "peaceful"))
605  pl->peaceful = value;
606  else if (!strcmp(buf, "no_shout"))
607  pl->no_shout = value;
608  else if (!strcmp(buf, "digestion"))
609  pl->digestion = value;
610  else if (!strcmp(buf, "pickup"))
611  pl->mode = value;
612  else if (!strcmp(buf, "outputs_sync"))
613  pl->outputs_sync = value;
614  else if (!strcmp(buf, "outputs_count"))
615  pl->outputs_count = value;
616  else if (!strcmp(buf, "map"))
617  sscanf(bufall, "map %s", pl->maplevel);
618  else if (!strcmp(buf, "savebed_map"))
619  sscanf(bufall, "savebed_map %s", pl->savebed_map);
620  else if (!strcmp(buf, "bed_x"))
621  pl->bed_x = value;
622  else if (!strcmp(buf, "bed_y"))
623  pl->bed_y = value;
624  else if (!strcmp(buf,"weapon_sp"))
625  sscanf(buf, "weapon_sp %f", &pl->weapon_sp);
626  else if (!strcmp(buf, "Str"))
627  pl->orig_stats.Str = value;
628  else if (!strcmp(buf, "Dex"))
629  pl->orig_stats.Dex = value;
630  else if (!strcmp(buf, "Con"))
631  pl->orig_stats.Con = value;
632  else if (!strcmp(buf, "Int"))
633  pl->orig_stats.Int = value;
634  else if (!strcmp(buf, "Pow"))
635  pl->orig_stats.Pow = value;
636  else if (!strcmp(buf, "Wis"))
637  pl->orig_stats.Wis = value;
638  else if (!strcmp(buf, "Cha"))
639  pl->orig_stats.Cha = value;
640  else if (!strcmp(buf, "usekeys")) {
641  if (!strcmp(bufall+8, "key_inventory\n"))
642  pl->usekeys = key_inventory;
643  else if (!strcmp(bufall+8, "keyrings\n"))
644  pl->usekeys = keyrings;
645  else if (!strcmp(bufall+8, "containers\n"))
646  pl->usekeys = containers;
647  else
648  LOG(llevDebug, "load_player: got unknown usekeys type: %s\n", bufall+8);
649  } else if (!strcmp(buf, "unapply")) {
650  if (!strcmp(bufall+8, "unapply_nochoice\n"))
652  else if (!strcmp(bufall+8, "unapply_never\n"))
653  pl->unapply = unapply_never;
654  else if (!strcmp(bufall+8, "unapply_always\n"))
655  pl->unapply = unapply_always;
656  else
657  LOG(llevDebug, "load_player: got unknown unapply type: %s\n", bufall+8);
658  } else if (!strcmp(buf, "lev_array")) {
659  for (i = 1; i <= value; i++) {
660  int j;
661 
662  fscanf(fp, "%d\n", &j);
663  pl->levhp[i] = j;
664  fscanf(fp, "%d\n", &j);
665  pl->levsp[i] = j;
666  fscanf(fp, "%d\n", &j);
667  pl->levgrace[i] = j;
668  }
669  } else if (!strcmp(buf, "party_rejoin_mode")) {
670  pl->rejoin_party = value;
671  } else if (!strcmp(buf, "party_rejoin_name")) {
672  party_name = strdup_local(bufall+strlen("party_rejoin_name")+1);
673  if (party_name && strlen(party_name) > 0)
674  party_name[strlen(party_name)-1] = '\0';
675  } else if (!strcmp(buf, "party_rejoin_password")) {
676  size_t len;
677 
678  snprintf(party_password, sizeof(party_password), "%s", bufall+strlen("party_rejoin_password")+1);
679  len = strlen(party_password);
680  /* Remove trailing \n if needed. If password is 8 chars long,
681  * snprintf would already have dropped the \n.
682  */
683  if (len > 0 && len < 8)
684  party_password[len-1] = '\0';
685  } else if (!strcmp(buf, "language")) {
686  if (value < 0 || value >= NUM_LANGUAGES)
687  value = 0;
688  pl->language = value;
689  }
690  } /* End of loop loading the character file */
691  remove_ob(op);
692  op->speed = 0;
693  update_ob_speed(op);
694  /*FIXME dangerous call, reset_object should be used to init freshly allocated obj struct!*/
695  reset_object(op);
696  op->contr = pl;
697  pl->ob = op;
698  /* this loads the standard objects values. */
699  load_object(fp, op, LO_NEWFILE, 0);
700  close_and_delete(fp, comp);
701 
703 
704  strncpy(pl->title, op->arch->clone.name, sizeof(pl->title)-1);
705  pl->title[sizeof(pl->title)-1] = '\0';
706 
707  /* If the map where the person was last saved does not exist,
708  * restart them on their home-savebed. This is good for when
709  * maps change between versions
710  * First, we check for partial path, then check to see if the full
711  * path (for unique player maps)
712  */
713  if (check_path(pl->maplevel, 1) == -1) {
714  if (check_path(pl->maplevel, 0) == -1) {
715  strcpy(pl->maplevel, pl->savebed_map);
716  op->x = pl->bed_x,
717  op->y = pl->bed_y;
718  /* if the map was a shop, the player can have unpaid items, remove them. */
719  remove_unpaid_objects(op, NULL, 1);
720  }
721  }
722 
723  /* If player saved beyond some time ago, and the feature is
724  * enabled, put the player back on his savebed map.
725  */
726  if ((settings.reset_loc_time > 0) && (elapsed_save_time > settings.reset_loc_time)) {
727  strcpy(pl->maplevel, pl->savebed_map);
728  op->x = pl->bed_x, op->y = pl->bed_y;
729  /* if the map was a shop, the player can have unpaid items, remove them. */
730  remove_unpaid_objects(op, NULL, 1);
731  }
732 
733  /* make sure he's a player--needed because of class change. */
734  op->type = PLAYER;
735 
736  enter_exit(op, NULL);
737 
738  pl->name_changed = 1;
739  pl->state = ST_PLAYING;
740 #ifdef AUTOSAVE
741  pl->last_save_tick = pticks;
742 #endif
743  op->carrying = sum_weight(op);
744 
745  link_player_skills(op);
746 
747  if (!legal_range(op, op->contr->shoottype))
748  op->contr->shoottype = range_none;
749 
750  /* if it's a dragon player, set the correct title here */
751  if (is_dragon_pl(op) && op->inv != NULL) {
752  object *tmp, *abil = NULL, *skin = NULL;
753 
754  for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
755  if (tmp->type == FORCE) {
756  if (strcmp(tmp->arch->name, "dragon_ability_force") == 0)
757  abil = tmp;
758  else if (strcmp(tmp->arch->name, "dragon_skin_force") == 0)
759  skin = tmp;
760  }
761  }
762  set_dragon_name(op, abil, skin);
763  }
764 
766  "Welcome Back!", NULL);
769  "%s has entered the game.",
770  "%s has entered the game.",
771  pl->ob->name);
772 
773  /* Lauwenmark : Here we handle the LOGIN global event */
775  op->contr->socket.update_look = 1;
776  /* If the player should be dead, call kill_player for them
777  * Only check for hp - if player lacks food, let the normal
778  * logic for that to take place. If player is permanently
779  * dead, and not using permadeath mode, the kill_player will
780  * set the play_again flag, so return.
781  */
782  if (op->stats.hp < 0) {
784  "Your character was dead last your played.",
785  NULL);
786  kill_player(op);
787  if (pl->state != ST_PLAYING)
788  return;
789  }
790  LOG(llevInfo, "LOGIN: Player named %s from ip %s\n", op->name,
791  op->contr->socket.host);
792 
793  /* Do this after checking for death - no reason sucking up bandwidth if
794  * the data isn't needed.
795  */
796  esrv_new_player(op->contr, op->weight+op->carrying);
797  /* Need to do these after esvr_new_player, as once the client
798  * sees that, it wipes any info it has about the player.
799  */
800  esrv_add_spells(op->contr, NULL);
801 
802  /* Need to call fix_object now - program modified so that it is not
803  * called during the load process (FLAG_NO_FIX_PLAYER set when
804  * saved)
805  * Moved ahead of the esrv functions, so proper weights will be
806  * sent to the client. Needs to be after esvr_add_spells, otherwise
807  * we'll try to update spells from fix_object.
808  */
809  fix_object(op);
810 
811  esrv_send_inventory(op, op);
812  esrv_send_pickup(pl);
813 
815 
816  /* can_use_shield is a new flag. However, the can_use.. seems to largely come
817  * from the class, and not race. I don't see any way to get the class information
818  * to then update this. I don't think this will actually break anything - anyone
819  * that can use armour should be able to use a shield. What this may 'break'
820  * are features new characters get, eg, if someone starts up with a Q, they
821  * should be able to use a shield. However, old Q's won't get that advantage.
822  */
823  if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
825 
826  /* Rejoin party if needed. */
827  if (pl->rejoin_party != party_rejoin_no && party_name != NULL) {
828  partylist *party;
829  for (party = get_firstparty(); party; party = party->next) {
830  if (strcmp(party_name, party->partyname) == 0)
831  break;
832  }
833  if (!party && pl->rejoin_party == party_rejoin_always) {
834  party = form_party(op, party_name);
835  snprintf(party->passwd, sizeof(party->passwd), "%s", party_password);
836  }
837  if (party && strcmp(party->passwd, party_password) == 0) {
838  pl->party = party;
839  snprintf(buf, MAX_BUF, "%s joins party %s", op->name, party->partyname);
840  send_party_message(op, buf);
841  }
842 
843  if (pl->party)
844  snprintf(buf, MAX_BUF, "Rejoined party %s.", party->partyname);
845  else
846  snprintf(buf, MAX_BUF, "Couldn't rejoined party %s: %s.", party_name, party ? "invalid password." : "no such party.");
848  buf, NULL);
849  }
850  if (party_name)
851  free(party_name);
852 
853  return;
854 }
sint16 bed_x
Definition: player.h:152
int check_name(player *me, const char *name)
Definition: login.c:173
char path[HUGE_BUF]
Definition: map.h:384
sint8 Int
Definition: living.h:78
int check_password(char *typed, char *crypted)
Definition: server.c:162
Definition: player.h:146
#define ST_GET_PARTY_PASSWORD
Definition: define.h:894
signed short sint16
Definition: global.h:72
uint32 pticks
Definition: time.c:56
void enter_exit(object *op, object *exit_ob)
Definition: server.c:740
void esrv_new_player(player *pl, uint32 weight)
Definition: request.c:868
void leave(player *pl, int draw_exit)
Definition: server.c:1234
#define SAVE_ERROR_OK
Definition: map.h:164
void delete_character(const char *name)
Definition: login.c:97
long strtol(register char *str, char **ptr, register int base)
Definition: porting.c:339
#define SET_FLAG(xyz, p)
Definition: define.h:510
#define NDI_ALL
Definition: newclient.h:220
char title[BIG_NAME]
Definition: player.h:216
sint8 last_level
Definition: player.h:175
uint32 name_changed
Definition: player.h:184
void make_path_to_file(const char *filename)
Definition: porting.c:764
char spellparam[MAX_BUF]
Definition: player.h:154
#define FLAG_USE_ARMOUR
Definition: define.h:592
void remove_directory(const char *path)
Definition: porting.c:192
struct obj * container
Definition: object.h:149
#define EVENT_LOGIN
Definition: plugin.h:84
#define FLAG_FRIENDLY
Definition: define.h:542
sint16 digestion
Definition: player.h:166
int save_player(object *op, int flag)
Definition: login.c:223
#define FLAG_NO_FIX_PLAYER
Definition: define.h:573
const char * playerdir
Definition: global.h:336
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:448
object clone
Definition: object.h:326
uint8 set_title
Definition: global.h:353
socket_struct socket
Definition: player.h:148
rangetype shoottype
Definition: player.h:153
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:414
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:307
uint32 mode
Definition: player.h:164
sint64 exp
Definition: living.h:88
void close_and_delete(FILE *fp, int compressed)
Definition: porting.c:748
int language
Definition: player.h:255
enum Sock_Status status
Definition: newserver.h:116
sint16 x
Definition: object.h:179
signed long sum_weight(object *op)
Definition: object.c:317
uint8 search_items
Definition: global.h:355
sint8 levsp[11]
Definition: player.h:219
int legal_range(object *op, int r)
Definition: c_range.c:282
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
char * partyname
Definition: player.h:124
#define FLAG_USE_SHIELD
Definition: define.h:533
void terminate_all_pets(object *owner)
Definition: pets.c:250
#define ST_PLAYING
Definition: define.h:886
char savebed_map[MAX_BUF]
Definition: player.h:151
#define NDI_DK_ORANGE
Definition: newclient.h:201
#define MAX_PASSWORD_FAILURES
Definition: newserver.h:110
char * host
Definition: newserver.h:125
sint16 gen_hp
Definition: player.h:167
uint16 outputs_sync
Definition: player.h:245
uint16 outputs_count
Definition: player.h:246
#define PLAYER
Definition: define.h:113
void esrv_add_spells(player *pl, object *spell)
Definition: request.c:1812
sint8 Con
Definition: living.h:78
#define FLAG_REMOVED
Definition: define.h:528
sint16 hp
Definition: living.h:81
static void wrong_password(object *op)
Definition: login.c:441
partylist * party
Definition: player.h:237
void get_name(object *op)
Definition: player.c:786
sint16 gen_grace
Definition: player.h:170
#define SAVE_FLAG_SAVE_UNPAID
Definition: map.h:131
void remove_ob(object *op)
Definition: object.c:1515
#define NDI_RED
Definition: newclient.h:198
const char * name_pl
Definition: object.h:168
unapplymode unapply
Definition: player.h:162
struct party_struct * next
Definition: player.h:123
enum _petmode petmode_t
#define LO_NEWFILE
Definition: loader.h:45
sint32 weight
Definition: object.h:216
#define NDI_ALL_DMS
Definition: newclient.h:221
uint32 peaceful
Definition: player.h:185
const char * tmpdir
Definition: global.h:343
sint8 Wis
Definition: living.h:78
struct mapdef * map
Definition: object.h:155
int is_dragon_pl(const object *op)
Definition: player.c:125
char search_str[MAX_BUF]
Definition: player.h:243
FILE * tempnam_secure(const char *dir, const char *pfx, char **filename)
Definition: porting.c:143
float weapon_sp
Definition: player.h:194
sint32 carrying
Definition: object.h:218
const char * name
Definition: object.h:167
living orig_stats
Definition: player.h:203
uint8 state
Definition: player.h:172
struct obj * below
Definition: object.h:145
int execute_global_event(int eventcode,...)
Definition: standalone.c:229
#define TRUE
Definition: exp.c:41
void confirm_password(object *op)
Definition: player.c:877
sint8 Cha
Definition: living.h:78
void check_score(object *op, int quiet)
Definition: hiscore.c:289
sint16 y
Definition: object.h:179
struct pl * contr
Definition: object.h:134
float speed
Definition: object.h:181
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
char * strdup_local(const char *str)
Definition: porting.c:310
party_rejoin_mode rejoin_party
Definition: player.h:242
#define FLAG_WIZ
Definition: define.h:527
#define MAX_BUF
Definition: define.h:81
#define MSG_TYPE_ADMIN
Definition: newclient.h:324
enum _bowtype bowtype_t
char own_title[MAX_NAME]
Definition: player.h:214
int save_object(FILE *fp, object *op, int flag)
uint32 explore
Definition: player.h:187
#define MIN(x, y)
Definition: define.h:67
sint8 Str
Definition: living.h:78
#define SAVE_FLAG_NO_REMOVE
Definition: map.h:132
object * ob
Definition: player.h:207
void remove_unpaid_objects(object *op, object *env, int free_items)
Definition: player.c:2943
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
sint16 bed_y
Definition: player.h:152
bowtype_t bowtype
Definition: player.h:155
#define FORCE
Definition: define.h:296
partylist * get_firstparty(void)
Definition: c_party.c:48
uint32 update_look
Definition: newserver.h:131
#define FREE_AND_COPY(sv, nv)
Definition: global.h:288
const char * localdir
Definition: global.h:335
partylist * form_party(object *op, const char *params)
Definition: c_party.c:65
char password[16]
Definition: player.h:227
living stats
Definition: object.h:219
int load_object(FILE *fp, object *op, int bufstate, int map_flags)
sint8 Dex
Definition: living.h:78
struct archt * arch
Definition: object.h:263
#define unlink(__a)
Definition: win32.h:67
void reset_object(object *op)
Definition: object.c:639
sint8 levgrace[11]
Definition: player.h:220
struct Settings settings
Definition: init.c:48
int verify_player(const char *name, char *password)
Definition: login.c:120
EXTERN long trying_emergency_save
Definition: global.h:211
#define SAVE_MODE
Definition: config.h:634
rangetype
Definition: player.h:52
#define MSG_TYPE_COMMAND
Definition: newclient.h:326
EXTERN char first_map_path[MAX_BUF]
Definition: global.h:229
void destroy_object(object *op)
Definition: login.c:201
#define NUM_LANGUAGES
Definition: languages.h:33
void update_ob_speed(object *op)
Definition: object.c:1008
void emergency_save(int flag)
Definition: login.c:51
EXTERN player * first_player
Definition: global.h:190
void link_player_skills(object *op)
Definition: skill_util.c:112
void send_party_message(object *op, char *msg)
Definition: c_party.c:285
int playername_ok(const char *cp)
Definition: player.c:230
struct pl * next
Definition: player.h:147
sint16 gen_sp
Definition: player.h:168
int check_path(const char *name, int prepend_dir)
Definition: map.c:216
int reset_loc_time
Definition: global.h:352
void esrv_send_pickup(player *pl)
Definition: request.c:1747
sint8 Pow
Definition: living.h:78
struct obj * inv
Definition: object.h:148
petmode_t petmode
Definition: player.h:156
#define NDI_UNIQUE
Definition: newclient.h:219
void final_free_player(player *pl)
Definition: init.c:328
char maplevel[MAX_BUF]
Definition: player.h:150
uint32 no_shout
Definition: player.h:188
usekeytype usekeys
Definition: player.h:161
void check_login(object *op)
Definition: login.c:473
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
#define MAX_NAME
Definition: define.h:87
sint8 levhp[11]
Definition: player.h:218
void kill_player(object *op)
Definition: player.c:3238
uint8 listening
Definition: player.h:174
void set_dragon_name(object *pl, const object *abil, const object *skin)
Definition: living.c:1566
#define MSG_TYPE_ADMIN_LOADSAVE
Definition: newclient.h:417
void free_object(object *ob)
Definition: object.c:1238
char * emergency_mapname
Definition: global.h:388
char write_buf[MAX_BUF]
Definition: player.h:225
uint8 password_fails
Definition: newserver.h:127
#define MSG_TYPE_ADMIN_LOGIN
Definition: newclient.h:418
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
FILE * open_and_uncompress(const char *name, int flag, int *compressed)
Definition: porting.c:724
const char * name
Definition: object.h:322
uint8 type
Definition: object.h:189
static void copy_file(const char *filename, FILE *fpout)
Definition: login.c:421
char passwd[9]
Definition: player.h:122