Crossfire Server, Trunk  R20513
server.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 
29 #ifndef WIN32
30 #include <unistd.h>
31 #endif
32 
33 /* FIXME: This is required on certain systems to get crypt(3) to work. */
34 #ifdef HAVE_CRYPT_H
35 #include <crypt.h>
36 #endif
37 
38 #include "object.h"
39 #include "path.h"
40 #include "random_maps/random_map.h"
41 #include "random_maps/rproto.h"
42 #include "sproto.h"
43 #include "tod.h"
44 #include "version.h"
45 
47 static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
48 
64 static char const* crypt_string(char const str[static 1], char const* salt) {
65 #if defined(WIN32) || (defined(__FreeBSD__))
66  return(str);
67 #else
68  char s[2];
69 
70  if (salt == NULL) {
71  /* Generate a two-character salt for the DES cipher.
72  * We want the salt to be in this character set.
73  */
74  static const char *const c =
75  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
76  s[0] = c[RANDOM()%(int)strlen(c)],
77  s[1] = c[RANDOM()%(int)strlen(c)];
78  } else {
79  s[0] = salt[0],
80  s[1] = salt[1];
81  }
82 
83  return crypt(str, s);
84 #endif
85 }
86 
87 char const* newhash(char const password[static 1]) {
88  return crypt_string(password, NULL);
89 }
90 
100 bool check_password(const char *typed, const char *crypted) {
101  // An empty hashed password only matches an empty input password.
102  if (strlen(crypted) == 0) {
103  return strlen(typed) == 0 ? true : false;
104  }
105 
106  return strcmp(crypt_string(typed, crypted), crypted) == 0;
107 }
108 
118 void enter_player_savebed(object *op) {
119  mapstruct *oldmap = op->map;
120  object *tmp;
121 
122  tmp = object_new();
123 
124  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
125  EXIT_X(tmp) = op->contr->bed_x;
126  EXIT_Y(tmp) = op->contr->bed_y;
127  enter_exit(op, tmp);
128  /* If the player has not changed maps and the name does not match
129  * that of the savebed, his savebed map is gone. Lets go back
130  * to the emergency path. Update what the players savebed is
131  * while we're at it.
132  */
133  if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) {
134  LOG(llevDebug, "Player %s savebed location %s is invalid - going to emergency location (%s)\n",
140  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
141  EXIT_X(tmp) = op->contr->bed_x;
142  EXIT_Y(tmp) = op->contr->bed_y;
143  enter_exit(op, tmp);
144  }
146 }
147 
159 static void enter_map(object *op, mapstruct *newmap, int x, int y) {
160  mapstruct *oldmap = op->map;
161 
162  if (out_of_map(newmap, x, y)) {
163  LOG(llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", newmap->path, x, y);
164  /* If op has invalid (probably -1,-1) coordinates, force them to a correct value, else issues later on. */
165  if (op->x == x)
166  op->x = MAP_ENTER_X(newmap);
167  if (op->y == y)
168  op->y = MAP_ENTER_Y(newmap);
169  x = MAP_ENTER_X(newmap);
170  y = MAP_ENTER_Y(newmap);
171  if (out_of_map(newmap, x, y)) {
172  LOG(llevError, "enter_map: map %s provides invalid default enter location (%d, %d) > (%d, %d)\n", newmap->path, x, y, MAP_WIDTH(newmap), MAP_HEIGHT(newmap));
174  "The exit is closed");
175  return;
176  }
177  }
178  /* try to find a spot for the player */
179  if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */
180  /* We try to find a spot for the player, starting closest in.
181  * We could use object_find_first_free_spot(), but that doesn't randomize it at all,
182  * So for example, if the north space is free, you would always end up there even
183  * if other spaces around are available.
184  * Note that for the second and third calls, we could start at a position other
185  * than one, but then we could end up on the other side of walls and so forth.
186  */
187  int i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE1+1);
188  if (i == -1) {
189  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE2+1);
190  if (i == -1)
191  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE);
192  }
193  if (i != -1) {
194  x += freearr_x[i];
195  y += freearr_y[i];
196  } else {
197  /* not much we can do in this case. */
198  LOG(llevInfo, "enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", newmap->path, x, y);
199  }
200  } /* end if looking for free spot */
201 
202  /* If it is a player login, he has yet to be inserted anyplace.
203  * otherwise, we need to deal with removing the playe here.
204  */
205  if (!QUERY_FLAG(op, FLAG_REMOVED))
206  object_remove(op);
207  if (op->map != NULL) {
208  /* Lauwenmark : Here we handle the MAPLEAVE global event */
210  }
211  /* object_remove clears these so they must be reset after the object_remove() call */
212  object_insert_in_map_at(op, newmap, NULL, INS_NO_WALK_ON, x, y);
213 
214  /* Lauwenmark : Here we handle the MAPENTER global event */
216 
217  newmap->timeout = 0;
218  object_set_enemy(op, NULL);
219 
220  if (op->contr) {
221  safe_strncpy(op->contr->maplevel, newmap->path,
222  sizeof(op->contr->maplevel));
223  op->contr->count = 0;
224  }
225 
226  /* Update any golems */
227  if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL) {
228  int i = object_find_free_spot(op->contr->ranges[range_golem], newmap, x, y, 1, SIZEOFFREE);
230  if (i == -1) {
233  op->contr->ranges[range_golem] = NULL;
234  op->contr->golem_count = 0;
235  } else {
236  object_insert_in_map_at(op->contr->ranges[range_golem], newmap, NULL, 0, x+freearr_x[i], y+freearr_y[i]);
238  }
239  }
240  op->direction = 0;
241 
242  /* since the players map is already loaded, we don't need to worry
243  * about pending objects.
244  */
245  pets_remove_all();
246 
247  /* If the player is changing maps, we need to do some special things
248  * Do this after the player is on the new map - otherwise the force swap of the
249  * old map does not work.
250  */
251  if (oldmap != newmap) {
252  if (oldmap) { /* adjust old map */
253  if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */
254  set_map_timeout(oldmap);
255  }
256  }
257  swap_below_max(newmap->path);
258 
259  if (op->type == PLAYER) {
260  map_newmap_cmd(&op->contr->socket);
262  }
263 }
264 
271 void set_map_timeout(mapstruct *oldmap) {
272 #if MAP_MAXTIMEOUT
273  oldmap->timeout = MAP_TIMEOUT(oldmap);
274  /* Do MINTIMEOUT first, so that MAXTIMEOUT is used if that is
275  * lower than the min value.
276  */
277 #if MAP_MINTIMEOUT
278  if (oldmap->timeout < MAP_MINTIMEOUT) {
279  oldmap->timeout = MAP_MINTIMEOUT;
280  }
281 #endif
282  if (oldmap->timeout > MAP_MAXTIMEOUT) {
283  oldmap->timeout = MAP_MAXTIMEOUT;
284  }
285 #else
286  /* save out the map */
287  swap_map(oldmap);
288 #endif /* MAP_MAXTIMEOUT */
289 }
290 
304 static char *clean_path(const char *file, char *newpath, int size) {
305  char *cp;
306 
307  snprintf(newpath, size, "%s", file);
308  for (cp = newpath; *cp != '\0'; cp++) {
309  if (*cp == '/')
310  *cp = '_';
311  }
312  return newpath;
313 }
314 
332 static char *unclean_path(const char *src, char *newpath, int size) {
333  char *cp;
334 
335  cp = strrchr(src, '/');
336  if (cp)
337  snprintf(newpath, size, "%s", cp+1);
338  else
339  snprintf(newpath, size, "%s", src);
340 
341  for (cp = newpath; *cp != '\0'; cp++) {
342  if (*cp == '_')
343  *cp = '/';
344  }
345  return newpath;
346 }
347 
348 
358 static void enter_random_map(object *pl, object *exit_ob) {
359  mapstruct *new_map;
360  char newmap_name[HUGE_BUF], buf[HUGE_BUF], *cp;
361  static int reference_number = 0;
362  RMParms rp;
363 
364  memset(&rp, 0, sizeof(RMParms));
365  rp.Xsize = -1;
366  rp.Ysize = -1;
367  rp.region = get_region_by_map(exit_ob->map);
368  if (exit_ob->msg)
369  set_random_map_variable(&rp, exit_ob->msg);
370  rp.origin_x = exit_ob->x;
371  rp.origin_y = exit_ob->y;
372  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
373 
374  /* If we have a final_map, use it as a base name to give some clue
375  * as where the player is. Otherwise, use the origin map.
376  * Take the last component (after the last slash) to give
377  * shorter names without bogus slashes.
378  */
379  if (rp.final_map[0]) {
380  cp = strrchr(rp.final_map, '/');
381  if (!cp)
382  cp = rp.final_map;
383  } else {
384  cp = strrchr(rp.origin_map, '/');
385  if (!cp)
386  cp = rp.origin_map;
387  /* Need to strip of any trailing digits, if it has them */
388  snprintf(buf, sizeof(buf), "%s", cp);
389  while (isdigit(buf[strlen(buf)-1]))
390  buf[strlen(buf)-1] = 0;
391  cp = buf;
392  }
393 
394  snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
395 
396  /* now to generate the actual map. */
397  new_map = generate_random_map(newmap_name, &rp, NULL);
398 
399  /* Update the exit_ob so it now points directly at the newly created
400  * random maps. Not that it is likely to happen, but it does mean that a
401  * exit in a unique map leading to a random map will not work properly.
402  * It also means that if the created random map gets reset before
403  * the exit leading to it, that the exit will no longer work.
404  */
405  if (new_map) {
406  int x, y;
407 
408  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
409  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
410  EXIT_PATH(exit_ob) = add_string(newmap_name);
411  snprintf(new_map->path, sizeof(new_map->path), "%s", newmap_name);
412  enter_map(pl, new_map, x, y);
413  }
414 }
415 
425 static void enter_fixed_template_map(object *pl, object *exit_ob) {
426  mapstruct *new_map;
427  char tmpnum[32], exitpath[HUGE_BUF], resultname[HUGE_BUF], tmpstring[HUGE_BUF], *sourcemap;
428  char new_map_name[MAX_BUF];
429 
430  /* Split the exit path string into two parts, one
431  * for where to store the map, and one for were
432  * to generate the map from.
433  */
434  snprintf(exitpath, sizeof(exitpath), "%s", EXIT_PATH(exit_ob)+2);
435  sourcemap = strchr(exitpath, '!');
436  if (!sourcemap) {
439  "The %s is closed.",
440  exit_ob->name);
441  /* Should only occur when no source map is set.
442  */
443  LOG(llevError, "enter_fixed_template_map: Exit %s (%d,%d) on map %s has no source template.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
444  return;
445  }
446  *sourcemap++ = '\0';
447 
448  /* If we are not coming from a template map, we can use relative directories
449  * for the map to generate from.
450  */
451  if (!exit_ob->map->is_template) {
452  /* We can't use exitpath directly, as sourcemap points there. */
453  path_combine_and_normalize(exit_ob->map->path, sourcemap, tmpstring, sizeof(tmpstring));
454  snprintf(exitpath, sizeof(exitpath), "%s", tmpstring);
455  sourcemap = exitpath;
456  }
457 
458  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
459  * of the exit, and the name of the map the exit is on, respectively.
460  */
461  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
462  replace(exitpath, "%x", tmpnum, resultname, sizeof(resultname));
463 
464  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
465  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
466  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
467 
468  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
469  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
470 
471  /* If we are coming from another template map, use reletive paths unless
472  * indicated otherwise.
473  */
474  if (exit_ob->map->is_template && (resultname[0] != '/')) {
475  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
476  } else {
477  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
478  }
479 
480  /* Attempt to load the map, if unable to, then
481  * create the map from the template.
482  */
483  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
484  if (!new_map) {
485  char path[MAX_BUF];
486 
487  create_pathname(sourcemap, path, MAX_BUF);
488  new_map = mapfile_load(path, MAP_PLAYER_UNIQUE);
489  }
490 
491  if (new_map) {
492  /* set the path of the map to where it should be
493  * so we don't just save over the source map.
494  */
495  snprintf(new_map->path, sizeof(new_map->path), "%s", new_map_name);
496  new_map->is_template = 1;
497  enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob));
498  } else {
501  "The %s is closed.",
502  exit_ob->name);
503  /* Should only occur when an invalid source map is set.
504  */
505  LOG(llevDebug, "enter_fixed_template_map: Exit %s (%d,%d) on map %s leads no where.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
506  }
507 }
508 
518 static void enter_random_template_map(object *pl, object *exit_ob) {
519  mapstruct *new_map;
520  char tmpnum[32], resultname[HUGE_BUF], tmpstring[HUGE_BUF];
521  char new_map_name[MAX_BUF];
522  RMParms rp;
523 
524  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
525  * of the exit, and the name of the map the exit is on, respectively.
526  */
527  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
528  replace(EXIT_PATH(exit_ob)+3, "%x", tmpnum, resultname, sizeof(resultname));
529 
530  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
531  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
532  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
533 
534  snprintf(tmpstring, sizeof(tmpstring), "%s", resultname);
535  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
536 
537  /* If we are coming from another template map, use reletive paths unless
538  * indicated otherwise.
539  */
540  if (exit_ob->map->is_template && (resultname[0] != '/')) {
541  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
542  } else {
543  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
544  }
545 
546  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
547  if (!new_map) {
548  memset(&rp, 0, sizeof(RMParms));
549  rp.Xsize = -1;
550  rp.Ysize = -1;
551  rp.region = get_region_by_map(exit_ob->map);
552  if (exit_ob->msg)
553  set_random_map_variable(&rp, exit_ob->msg);
554  rp.origin_x = exit_ob->x;
555  rp.origin_y = exit_ob->y;
556  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
557 
558  /* now to generate the actual map. */
559  new_map = generate_random_map(new_map_name, &rp, NULL);
560  }
561 
562  /* Update the exit_ob so it now points directly at the newly created
563  * random maps. Not that it is likely to happen, but it does mean that a
564  * exit in a unique map leading to a random map will not work properly.
565  * It also means that if the created random map gets reset before
566  * the exit leading to it, that the exit will no longer work.
567  */
568  if (new_map) {
569  int x, y;
570 
571  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
572  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
573  new_map->is_template = 1;
574  enter_map(pl, new_map, x, y);
575  }
576 }
577 
586 static void enter_unique_map(object *op, object *exit_ob) {
587  char apartment[HUGE_BUF], path[MAX_BUF];
588  mapstruct *newmap;
589 
590  if (EXIT_PATH(exit_ob)[0] == '/') {
591  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
592  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
593  if (!newmap) {
594  create_pathname(EXIT_PATH(exit_ob), path, sizeof(path));
595  newmap = mapfile_load(path, MAP_PLAYER_UNIQUE);
596  }
597  } else { /* relative directory */
598  char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp;
599 
600  if (exit_ob->map->unique) {
601  unclean_path(exit_ob->map->path, reldir, sizeof(reldir));
602 
603  /* Need to copy this over, as clean_path only has one static return buffer */
604  clean_path(reldir, tmpc, sizeof(tmpc));
605  /* Remove final component, if any */
606  if ((cp = strrchr(tmpc, '_')) != NULL)
607  *cp = 0;
608 
609  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s_%s", settings.localdir, settings.playerdir, op->name, tmpc, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
610 
611  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
612  if (!newmap) {
613  create_pathname(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob), tmpc, sizeof(tmpc)), path, sizeof(path));
614  newmap = mapfile_load(path, MAP_PLAYER_UNIQUE);
615  }
616  } else {
617  /* The exit is unique, but the map we are coming from is not unique. So
618  * use the basic logic - don't need to demangle the path name
619  */
620  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
621  snprintf(apartment, sizeof(apartment), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, clean_path(reldir, path, sizeof(path)));
622  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
623  if (!newmap) {
624  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
625  newmap = ready_map_name(reldir, 0);
626  if (newmap)
627  apply_auto_fix(newmap);
628  }
629  }
630  }
631 
632  if (newmap) {
633  snprintf(newmap->path, sizeof(newmap->path), "%s", apartment);
634  newmap->unique = 1;
635  enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob));
636  } else {
639  "The %s is closed.",
640  exit_ob->name);
641  /* Perhaps not critical, but I would think that the unique maps
642  * should be new enough this does not happen. This also creates
643  * a strange situation where some players could perhaps have visited
644  * such a map before it was removed, so they have the private
645  * map, but other players can't get it anymore.
646  */
647  LOG(llevDebug, "enter_unique_map: Exit %s (%d,%d) on map %s is leads no where.\n", exit_ob->name, exit_ob->x, exit_ob->y, exit_ob->map->path);
648  }
649 }
650 
651 void enter_player_maplevel(object *op) {
652  int flags = 0, x = op->x, y = op->y;
653  mapstruct *newmap;
654 
655  assert(op != NULL);
656  assert(op->type == PLAYER);
657 
658  /* Hypothetically, I guess its possible that a standard map matches
659  * the localdir, but that seems pretty unlikely - unlikely enough that
660  * I'm not going to attempt to try to deal with that possibility.
661  * We use the fact that when a player saves on a unique map, it prepends
662  * the localdir to that name. So its an easy way to see of the map is
663  * unique or not.
664  */
665  if (!strncmp(op->contr->maplevel, settings.localdir, strlen(settings.localdir)))
666  flags = MAP_PLAYER_UNIQUE;
667 
668  /* newmap returns the map (if already loaded), or loads it for us. */
669  newmap = ready_map_name(op->contr->maplevel, flags);
670  if (!newmap) {
672  x = settings.emergency_x;
673  y = settings.emergency_y;
674  if (!newmap) {
675  LOG(llevError, "Fatal: Could not load emergency map!\n");
676  abort();
677  }
678 
680  "You find yourself somewhere unexpected...");
681  }
682 
683  /* as a special case, if coordinates are (-1, -1), then the item should
684  * be put at the default location. Used for loginmethod 0 (old clients). */
685  if (x == -1 && y == -1) {
686  x = MAP_ENTER_X(newmap);
687  y = MAP_ENTER_Y(newmap);
688  }
689 
690  enter_map(op, newmap, x, y);
691 }
692 
706 void enter_exit(object *op, object *exit_ob) {
707 #define PORTAL_DESTINATION_NAME "Town portal destination" /* this one should really be in a header file */
708  /* It may be nice to support other creatures moving across
709  * exits, but right now a lot of the code looks at op->contr,
710  * so thta is an RFE.
711  */
712  if (op->type != PLAYER)
713  return;
714 
715  /* Need to remove player from transport */
716  if (op->contr->transport)
717  ob_apply(op->contr->transport, op, AP_UNAPPLY);
718 
719  assert(exit_ob != NULL);
720  assert(EXIT_PATH(exit_ob) != NULL);
721 
722  /* check to see if we make a template map */
723  if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '@') {
724  if (EXIT_PATH(exit_ob)[2] == '!') {
725  /* generate a template map randomly */
726  enter_random_template_map(op, exit_ob);
727  } else {
728  /* generate a template map from a fixed template */
729  enter_fixed_template_map(op, exit_ob);
730  }
731  }
732  /* check to see if we make a randomly generated map */
733  else if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '!') {
734  enter_random_map(op, exit_ob);
735  } else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) {
736  enter_unique_map(op, exit_ob);
737  } else {
738  int x = EXIT_X(exit_ob), y = EXIT_Y(exit_ob);
739  /* 'Normal' exits that do not do anything special
740  * Simple enough we don't need another routine for it.
741  */
742  mapstruct *newmap;
743  if (exit_ob->map) {
744  char tmp_path[HUGE_BUF];
745 
746  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), tmp_path, sizeof(tmp_path));
747  newmap = ready_map_name(tmp_path, 0);
748  /* Random map was previously generated, but is no longer about. Lets generate a new
749  * map.
750  */
751  if (!newmap && !strncmp(EXIT_PATH(exit_ob), "/random/", 8)) {
752  /* Maps that go down have a message set. However, maps that go
753  * up, don't. If the going home has reset, there isn't much
754  * point generating a random map, because it won't match the maps.
755  */
756  if (exit_ob->msg) {
757  enter_random_map(op, exit_ob);
758  } else {
761  "The %s is closed.",
762  exit_ob->name);
763  return;
764  }
765 
766  /* For exits that cause damages (like pits). Don't know if any
767  * random maps use this or not.
768  */
769  if (exit_ob->stats.dam && op->type == PLAYER)
770  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
771  return;
772  }
773  } else {
774  /* For word of recall and other force objects
775  * They contain the full pathname of the map to go back to,
776  * so we don't need to normalize it.
777  * But we do need to see if it is unique or not
778  */
779  if (!strncmp(EXIT_PATH(exit_ob), settings.localdir, strlen(settings.localdir)))
780  newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE);
781  else
782  newmap = ready_map_name(EXIT_PATH(exit_ob), 0);
783  }
784  if (!newmap) {
785  if (exit_ob->name)
788  "The %s is closed.",
789  exit_ob->name);
790  /* don't cry to momma if name is not set - as in tmp objects
791  * used by the savebed code and character creation */
792  return;
793  }
794 
795  if (x == -1 && y == -1) {
796  x = MAP_ENTER_X(newmap);
797  y = MAP_ENTER_Y(newmap);
798  }
799 
800  /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */
801  if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) {
802  object *tmp;
803 
804  /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */
806  if (tmp) {
807  object_remove(tmp);
809  }
810 
811  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), op->contr->savebed_map, sizeof(op->contr->savebed_map));
812  op->contr->bed_x = EXIT_X(exit_ob), op->contr->bed_y = EXIT_Y(exit_ob);
813  save_player(op, 1);
814  }
815 
816  enter_map(op, newmap, x, y);
817  }
818 
819  LOG(llevDebug, "%s enters %s\n", op->name, EXIT_PATH(exit_ob));
820 
821  /* For exits that cause damages (like pits) */
822  if (exit_ob->stats.dam && op->type == PLAYER)
823  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
824 }
825 
831 static void process_players1(void) {
832  int flag;
833  player *pl, *plnext;
834 
835  /* Basically, we keep looping until all the players have done their actions. */
836  for (flag = 1; flag != 0; ) {
837  flag = 0;
838  for (pl = first_player; pl != NULL; pl = plnext) {
839  plnext = pl->next; /* In case a player exits the game in handle_player() */
840 
841  if (pl->ob == NULL)
842  continue;
843 
844  /* Only do this on the first pass - what we are recording
845  * here is the number of ticks the player has been online - not
846  * how many actions/moves the player has done.
847  */
848  if (!flag) pl->ticks_played++;
849 
851  if (pl->followed_player) {
853  if (followed && followed->ob && followed->ob->map) {
854  rv_vector rv;
855 
856  if (!get_rangevector(pl->ob, followed->ob, &rv, 0) || rv.distance > 4) {
857  int space = object_find_free_spot(pl->ob, followed->ob->map, followed->ob->x, followed->ob->y, 1, 25);
858  if (space == -1)
860  space = 0;
861  object_remove(pl->ob);
862  object_insert_in_map_at(pl->ob, followed->ob->map, NULL, 0, followed->ob->x+freearr_x[space], followed->ob->y+freearr_y[space]);
863  map_newmap_cmd(&pl->socket);
865  }
866  } else {
867  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Player %s left or ambiguous name.", pl->followed_player);
869  }
870  }
872  if (pl->ob->speed_left > 0) {
873  if (handle_newcs_player(pl->ob))
874  flag = 1;
875  } /* end if player has speed left */
876 
877  /* If the player is not actively playing, don't make a
878  * backup save - nothing to save anyway. Plus, the
879  * map may not longer be valid. This can happen when the
880  * player quits - they exist for purposes of tracking on the map,
881  * but don't actually reside on any actual map.
882  */
883  if (QUERY_FLAG(pl->ob, FLAG_REMOVED))
884  continue;
885 
886 #ifdef AUTOSAVE
887  /* check for ST_PLAYING state so that we don't try to save off when
888  * the player is logging in.
889  */
890  if ((pl->last_save_tick+AUTOSAVE) < pticks && pl->state == ST_PLAYING) {
891  /* Don't save the player on unholy ground. Instead, increase the
892  * tick time so it will be about 10 seconds before we try and save
893  * again.
894  */
895  if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL)&P_NO_CLERIC) {
896  pl->last_save_tick += 100;
897  } else {
898  save_player(pl->ob, 1);
899  pl->last_save_tick = pticks;
900  hiscore_check(pl->ob, 1);
901  }
902  }
903 #endif
904  } /* end of for loop for all the players */
905  } /* for flag */
906  for (pl = first_player; pl != NULL; pl = pl->next) {
907  int has_action = 1;
908 
909  pl->ob->weapon_speed_left += pl->ob->weapon_speed;
910  if (pl->ob->weapon_speed_left > 1.0)
911  pl->ob->weapon_speed_left = 1.0;
912 
913  pl->socket.sounds_this_tick = 0;
914 
915  if (settings.casting_time == TRUE) {
916  if (pl->ob->casting_time > 0) {
917  pl->ob->casting_time--;
918  has_action = 0;
919  }
920  }
921  /* If the character is idle (standing around resting) increase
922  * regen rates.
923  */
924  if (has_action && pl->ob->speed_left > 0) {
925  pl->ob->last_heal -= 2;
926  pl->ob->last_sp -= 2;
927  pl->ob->last_grace -= 2;
928  pl->ob->last_eat += 2; /* Slow down food consumption */
929  }
930  do_some_living(pl->ob);
931  }
932 }
933 
941 static void process_players2(void) {
942  player *pl;
943 
944  /* Then check if any players should use weapon-speed instead of speed */
945  for (pl = first_player; pl != NULL; pl = pl->next) {
946  /* The code that did weapon_sp handling here was out of place -
947  * this isn't called until after the player has finished there
948  * actions, and is thus out of place. All we do here is bounds
949  * checking.
950  */
951  if (pl->has_hit) {
952  /* This needs to be here - if the player is running, we need to
953  * clear this each tick, but new commands are not being received
954  * so execute_newserver_command() is never called
955  */
956  pl->has_hit = 0;
957  } else if (pl->ob->speed_left > pl->ob->speed)
958  pl->ob->speed_left = pl->ob->speed;
959  }
960 }
961 
962 #define SPEED_DEBUG
963 
967 void process_events(void) {
968  object *op;
969  object marker;
970  tag_t tag;
971 
973 
974  memset(&marker, 0, sizeof(object));
975  /* Put marker object at beginning of active list */
976  marker.active_next = active_objects;
977 
978  if (marker.active_next)
979  marker.active_next->active_prev = &marker;
980  marker.active_prev = NULL;
981  active_objects = &marker;
982 
983  while (marker.active_next) {
984  op = marker.active_next;
985  tag = op->count;
986 
987  /* Move marker forward - swap op and marker */
988  op->active_prev = marker.active_prev;
989 
990  if (op->active_prev)
991  op->active_prev->active_next = op;
992  else
993  active_objects = op;
994 
995  marker.active_next = op->active_next;
996 
997  if (marker.active_next)
998  marker.active_next->active_prev = &marker;
999  marker.active_prev = op;
1000  op->active_next = &marker;
1001 
1002  /* Now process op */
1003  if (QUERY_FLAG(op, FLAG_FREED)) {
1004  LOG(llevError, "BUG: process_events(): Free object on list\n");
1005  op->speed = 0;
1006  object_update_speed(op);
1007  continue;
1008  }
1009 
1010  /* I've seen occasional crashes due to this - the object is removed,
1011  * and thus the map it points to (last map it was on) may be bogus
1012  * The real bug is to try to find out the cause of this - someone
1013  * is probably calling object_remove() without either an insert_ob or
1014  * object_free_drop_inventory() afterwards, leaving an object dangling.
1015  * But I'd rather log this and continue on instead of crashing.
1016  * Don't remove players - when a player quits, the object is in
1017  * sort of a limbo, of removed, but something we want to keep
1018  * around.
1019  */
1020  if (QUERY_FLAG(op, FLAG_REMOVED)
1021  && op->type != PLAYER
1022  && op->map
1023  && op->map->in_memory != MAP_IN_MEMORY) {
1024  StringBuffer *sb;
1025  char *diff;
1026 
1027  LOG(llevError, "BUG: process_events(): Removed object on list\n");
1028  sb = stringbuffer_new();
1029  object_dump(op, sb);
1030  diff = stringbuffer_finish(sb);
1031  LOG(llevError, "%s\n", diff);
1032  free(diff);
1034  continue;
1035  }
1036 
1037  if (!op->speed) {
1038  LOG(llevError, "BUG: process_events(): Object %s has no speed, but is on active list\n", op->arch->name);
1039  object_update_speed(op);
1040  continue;
1041  }
1042 
1043  if (op->map == NULL
1044  && op->env == NULL
1045  && op->name
1046  && op->type != MAP) {
1047  LOG(llevError, "BUG: process_events(): Object without map or inventory is on active list: %s (%d)\n", op->name, op->count);
1048  op->speed = 0;
1049  object_update_speed(op);
1050  continue;
1051  }
1052 
1053  /* Seen some cases where process_object() is crashing because
1054  * the object is on a swapped out map. But can't be sure if
1055  * something in the chain of events caused the object to
1056  * change maps or was just never removed - this will
1057  * give some clue as to its state before call to
1058  * process_object
1059  */
1060  if (op->map && op->map->in_memory != MAP_IN_MEMORY) {
1061  LOG(llevError, "BUG: process_events(): Processing object on swapped out map: %s (%d), map=%s\n", op->name, op->count, op->map->path);
1062  }
1063 
1064  /* Animate the object. Bug of feature that andim_speed
1065  * is based on ticks, and not the creatures speed?
1066  */
1067  if ((op->anim_speed && op->last_anim >= op->anim_speed)
1068  || (op->temp_animation_id && op->last_anim >= op->temp_anim_speed)) {
1069  op->state++;
1070  if ((op->type == PLAYER) || (op->type == MONSTER))
1071  animate_object(op, op->facing);
1072  else
1073  animate_object(op, op->direction);
1074  op->last_anim = 1;
1075  } else {
1076  op->last_anim++;
1077  }
1078 
1079  if (op->speed_left > 0) {
1080  --op->speed_left;
1081  process_object(op);
1082  if (object_was_destroyed(op, tag))
1083  continue;
1084  }
1085  if (settings.casting_time == TRUE && op->casting_time > 0)
1086  op->casting_time--;
1087  if (op->speed_left <= 0)
1088  op->speed_left += FABS(op->speed);
1089  }
1090 
1091  /* Remove marker object from active list */
1092  if (marker.active_prev != NULL)
1093  marker.active_prev->active_next = NULL;
1094  else
1095  active_objects = NULL;
1096 
1097  process_players2();
1098 }
1099 
1105 void clean_tmp_files(void) {
1106  mapstruct *m, *next;
1107 
1108  LOG(llevInfo, "Cleaning up...\n");
1109 
1110  /* We save the maps - it may not be intuitive why, but if there are unique
1111  * items, we need to save the map so they get saved off. Perhaps we should
1112  * just make a special function that only saves the unique items.
1113  */
1114  for (m = first_map; m != NULL; m = next) {
1115  next = m->next;
1116  if (m->in_memory == MAP_IN_MEMORY) {
1117  /* If we want to reuse the temp maps, swap it out (note that will also
1118  * update the log file. Otherwise, save the map (mostly for unique item
1119  * stuff). Note that the clean_tmp_map is called after the end of
1120  * the for loop but is in the #else bracket. IF we are recycling the maps,
1121  * we certainly don't want the temp maps removed.
1122  */
1123 
1124  /* XXX The above comment is dead wrong */
1126  swap_map(m);
1127  else {
1128  save_map(m, SAVE_MODE_NORMAL); /* note we save here into a overlay map */
1129  clean_tmp_map(m);
1130  }
1131  }
1132  }
1133  write_todclock(); /* lets just write the clock here */
1134 }
1135 
1137 void cleanup(void) {
1138  LOG(llevDebug, "Cleanup called. freeing data.\n");
1139  clean_tmp_files();
1141  accounts_save();
1142 
1143 #ifdef MEMORY_DEBUG
1144  free_all_maps();
1145  free_style_maps();
1146 #endif
1147  cleanupPlugins();
1148 #ifdef MEMORY_DEBUG
1149  free_all_archs();
1152  free_all_images();
1154  free_all_recipes();
1156  free_all_god();
1157  free_all_anim();
1158  i18n_free();
1159  free_loader();
1160  free_globals();
1161  free_server();
1163  free_knowledge();
1164  free_quest();
1166  /* See what the string data that is out there that hasn't been freed. */
1167  /* LOG(llevDebug, "%s", ss_dump_table(0xff));*/
1168 #endif
1169  exit(0);
1170 }
1171 
1180 void leave(player *pl, int draw_exit) {
1181  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
1182  pets_terminate_all(pl->ob);
1183  object_remove(pl->ob);
1184  }
1185 
1186  pl->socket.status = Ns_Dead;
1187  LOG(llevInfo, "logout: %s from %s\n", pl->ob->name, pl->socket.host);
1188 
1189  strcpy(pl->ob->contr->killer, "left");
1190  hiscore_check(pl->ob, 1);
1191 
1192  /* If this player is the captain of the transport, need to do
1193  * some extra work. By the time we get here, object_remove()
1194  * should have already been called.
1195  */
1196  if (pl->transport && pl->transport->contr == pl) {
1197  /* If inv is a non player, inv->contr will be NULL, but that
1198  * is OK.
1199  */
1200  if (pl->transport->inv)
1201  pl->transport->contr = pl->transport->inv->contr;
1202  else
1203  pl->transport->contr = NULL;
1204 
1205  if (pl->transport->contr) {
1206  char name[MAX_BUF];
1207 
1208  query_name(pl->transport, name, MAX_BUF);
1211  "%s has left. You are now the captain of %s",
1212  pl->ob->name, name);
1213  }
1214  }
1215 
1216  if (pl->ob->map) {
1217  if (pl->ob->map->in_memory == MAP_IN_MEMORY)
1218  pl->ob->map->timeout = MAP_TIMEOUT(pl->ob->map);
1219  pl->ob->map = NULL;
1220  }
1221  pl->ob->type = DEAD_OBJECT; /* To avoid problems with inventory window */
1222  party_leave(pl->ob);
1223  /* If a hidden dm dropped connection do not create
1224  * inconsistencies by showing that they have left the game
1225  */
1226  if (!(QUERY_FLAG(pl->ob, FLAG_WIZ) && pl->ob->contr->hidden)
1227  && (pl != NULL && draw_exit) && (pl->state != ST_GET_NAME && pl->state != ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD))
1230  "%s left the game.",
1231  pl->ob->name);
1232 }
1233 
1241 int forbid_play(void) {
1242 #if !defined(_IBMR2) && !defined(___IBMR2) && defined(PERM_FILE)
1243  char buf[MAX_BUF], day[MAX_BUF];
1244  FILE *fp;
1245  time_t clock;
1246  struct tm *tm;
1247  int i, start, stop, forbit = 0;
1248 
1249  clock = time(NULL);
1250  tm = (struct tm *)localtime(&clock);
1251 
1252  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, PERM_FILE);
1253  if ((fp = fopen(buf, "r")) == NULL)
1254  return 0;
1255 
1256  while (fgets(buf, sizeof(buf), fp)) {
1257  if (buf[0] == '#')
1258  continue;
1259  if (!strncmp(buf, "msg", 3)) {
1260  if (forbit)
1261  while (fgets(buf, sizeof(buf), fp)) /* print message */
1262  fputs(buf, logfile);
1263  break;
1264  } else if (sscanf(buf, "%s %d%*c%d\n", day, &start, &stop) != 3) {
1265  LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n");
1266  continue;
1267  }
1268 
1269  for (i = 0; i < 7; i++) {
1270  if (!strncmp(buf, days[i], 3)
1271  && (tm->tm_wday == i)
1272  && (tm->tm_hour >= start)
1273  && (tm->tm_hour < stop))
1274  forbit = 1;
1275  }
1276  }
1277 
1278  fclose(fp);
1279 
1280  return forbit;
1281 #else
1282  return 0;
1283 #endif
1284 }
1285 
1289 static void server_check_shutdown(void) {
1290  /* When to remind players of an imminent apocalypse. */
1291  const int warn_times[] = {120, 60, 30, 15, 10, 5, 3, 2, 1};
1292  static int next_warn = 0;
1293 
1294  time_t time_left;
1295  unsigned int i;
1296 
1297  /* Zero means that no shutdown is pending. */
1298  if (cmd_shutdown_time == 0) {
1299  return;
1300  }
1301 
1302  /* Remind players about the upcoming shutdown. */
1303  time_left = cmd_shutdown_time - time(NULL);
1304 
1305  for (i = next_warn; i < sizeof(warn_times) / sizeof(int); i++) {
1306  if (warn_times[i] == (int)ceil(time_left / 60.0)) {
1309  "Server shutting down in %d minutes.", warn_times[i]);
1310  next_warn = i + 1;
1311  break;
1312  }
1313  }
1314 
1315  /* Shutdown time has arrived; bring server down. */
1316  if (time_left <= 0) {
1318  MSG_TYPE_ADMIN_DM, "The server has shut down.");
1319 
1320  /* TODO: Kick everyone out and save player files? */
1321  cleanup();
1322  }
1323 }
1324 
1325 extern unsigned long todtick;
1326 
1341 static void do_specials(void) {
1342  if (!(pticks%10))
1344 
1345  if (pticks % 51 == 0) {
1347  }
1348 
1349 #ifdef WATCHDOG
1350  if (!(pticks%503))
1351  watchdog();
1352 #endif
1353 
1354  if (!(pticks%PTICKS_PER_CLOCK))
1355  tick_the_clock();
1356 
1357  if (!(pticks%509))
1358  flush_old_maps(); /* Clears the tmp-files of maps which have reset */
1359 
1360  if (!(pticks%2503))
1361  fix_weight(); /* Hack to fix weightproblems caused by bugs */
1362 
1363  if (!(pticks%2521))
1364  metaserver_update(); /* 2500 ticks is about 5 minutes */
1365 
1366  if (!(pticks%2531))
1367  accounts_save();
1368 
1369  if (!(pticks%5003))
1371 
1372  if (!(pticks%5009))
1374 
1375  if (!(pticks%5011))
1377 
1378  if (!(pticks%12503))
1379  fix_luck();
1380 }
1381 
1390 void server_main(int argc, char *argv[]) {
1391 #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */
1392  _fmode = _O_BINARY;
1393  bRunning = 1;
1394 #endif
1395 
1396 #ifndef WIN32
1397  /* Here we check that we aren't root or suid */
1398  if (getuid() == 0 || geteuid() == 0) {
1399  fprintf(stderr,
1400  "Running crossfire-server as root is a bad idea; aborting!\n"
1401  "Please run it again as a normal, unprivileged user.\n");
1402  exit(EXIT_FAILURE);
1403  }
1404 #endif
1405 
1406 #ifdef DEBUG_MALLOC_LEVEL
1407  malloc_debug(DEBUG_MALLOC_LEVEL);
1408 #endif
1409 
1410  init(argc, argv);
1411  initPlugins(); /* GROS - Init the Plugins */
1412 #ifdef WIN32
1413  while (bRunning) {
1414 #else
1415  while (TRUE) {
1416 #endif
1417  nroferrors = 0;
1418 
1419  do_server();
1420  process_events(); /* "do" something with objects with speed */
1421  cftimer_process_timers(); /* Process the crossfire Timers */
1422  /* Lauwenmark : Here we handle the CLOCK global event */
1424  check_active_maps(); /* Removes unused maps after a certain timeout */
1425  do_specials(); /* Routines called from time to time. */
1426 
1427  sleep_delta(); /* Sleep proper amount of time before next tick */
1428  }
1429 
1430  /* This is unreachable. */
1431  abort();
1432 }
void enter_exit(object *op, object *exit_ob)
Tries to move &#39;op&#39; to exit_ob.
Definition: server.c:706
EXTERN FILE * logfile
Used by server/daemon.c.
Definition: global.h:144
float weapon_speed_left
How much speed is left to spend this round.
Definition: object.h:331
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
#define AP_UNAPPLY
Item is to be remvoed.
Definition: define.h:611
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
int find_dir_2(int x, int y)
Computes a direction which you should travel to move of x and y.
Definition: object.c:3600
void free_all_maps(void)
Frees all allocated maps.
Definition: map.c:1963
char const * newhash(char const password[static 1])
Definition: server.c:87
void leave(player *pl, int draw_exit)
Player logs out, or was disconnected.
Definition: server.c:1180
#define MSG_TYPE_MISC
Messages that don&#39;t go elsewhere.
Definition: newclient.h:389
One player.
Definition: player.h:92
Random map parameters.
Definition: random_map.h:14
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:318
mapstruct * mapfile_load(const char *map, int flags)
Opens the file "filename" and reads information about the map from the given file, and stores it in a newly allocated mapstruct.
Definition: map.c:1235
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
Main random map routine.
Definition: random_map.c:74
void do_server(void)
This checks the sockets for input and exceptions, does the right thing.
Definition: loop.c:501
Information.
Definition: logger.h:12
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:380
Definition: object.h:125
void enter_player_savebed(object *op)
This is a basic little function to put the player back to his savebed.
Definition: server.c:118
void free_quest_definitions(void)
Free all quest definitions and steps.
Definition: quest.c:1307
void cleanup(void)
Clean up everything and exit.
Definition: server.c:1137
static void enter_random_map(object *pl, object *exit_ob)
The player is trying to enter a randomly generated map.
Definition: server.c:358
static void do_specials(void)
Collection of functions to call from time to time.
Definition: server.c:1341
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:246
int16_t bed_x
Definition: player.h:98
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
Defines for the ingame clock, ticks management and weather system.
void object_free_all_data(void)
Destroys all allocated objects.
Definition: object.c:522
#define MSG_TYPE_COMMAND_FAILURE
Failed result from command.
Definition: newclient.h:511
void do_some_living(object *op)
Regenerate hp/sp/gr, decreases food.
Definition: player.c:3286
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:417
void metaserver_update(void)
Updates our info in the metaserver Note that this is used for both metaserver1 and metaserver2 - for ...
Definition: metaserver.c:49
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:418
int16_t players
How many players are on this level right now.
Definition: map.h:344
void player_update_bg_music(object player[static 1])
Definition: sounds.c:152
char final_map[RM_SIZE]
If not empty, the path of the final map this whole maze leads to.
Definition: random_map.h:52
char * create_pathname(const char *name, char *buf, size_t size)
Get the full path to a map file.
Definition: map.c:104
int save_player(object *op, int flag)
Saves a player to disk.
Definition: login.c:211
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:345
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.c:1803
const char * playerdir
Where the player files are.
Definition: global.h:246
int32_t last_heal
Last healed.
Definition: object.h:357
#define MAP_ENTER_X(m)
Default X coordinate for map enter.
Definition: map.h:85
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
#define EVENT_MAPLEAVE
A player left a map.
Definition: plugin.h:91
Random map related variables.
uint32_t is_template
If set, this is a template map.
Definition: map.h:338
uint32_t pticks
?
Definition: time.c:45
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:80
socket_struct socket
Socket information for this player.
Definition: player.h:94
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
#define ST_CONFIRM_PASSWORD
New character, confirm password.
Definition: define.h:584
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.c:74
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:358
object * ranges[range_size]
Object for each range.
Definition: player.h:103
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:533
#define AUTOSAVE
How often (in seconds) the player is saved if he drops things.
Definition: config.h:647
int8_t sounds_this_tick
Number of sounds sent this tick.
Definition: newserver.h:133
void swap_below_max(const char *except_level)
Tries to swap out maps which are still in memory, because of MAP_TIMEOUT until used objects is below ...
Definition: swap.c:242
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Find object in inventory by type and slaying.
Definition: object.c:4049
enum Sock_Status status
Definition: newserver.h:100
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:68
#define TRUE
Definition: compat.h:10
void party_leave(object *op)
Makes a player leave his party.
Definition: party.c:104
#define PERM_FILE
You can restrict playing in certain times by creating a PERMIT_FILE in CONFDIR.
Definition: config.h:499
#define SAVE_MODE_NORMAL
No special handling.
Definition: map.h:120
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.c:56
method_ret ob_apply(object *op, object *applier, int aflags)
Applies an object.
Definition: ob_methods.c:42
void fix_weight(void)
Check recursively the weight of all players, and fix what needs to be fixed.
Definition: player.c:3875
void enter_player_maplevel(object *op)
Move a player to its stored map level.
Definition: server.c:651
uint8_t temp_anim_speed
Ticks between temporary animation-frames.
Definition: object.h:420
void i18n_free(void)
Clears all i18n-related data.
Definition: languages.c:252
void clean_friendly_list(void)
It traverses the friendly list removing objects that should not be here (ie, do not have friendly fla...
Definition: friend.c:111
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:23
void free_quest(void)
Free all quest status structures.
Definition: quest.c:1289
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:132
void pets_terminate_all(object *owner)
Removes all pets someone owns.
Definition: pets.c:231
static void enter_unique_map(object *op, object *exit_ob)
Player is entering a unique map.
Definition: server.c:586
int swap_map(mapstruct *map)
Swaps a map to disk.
Definition: swap.c:135
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
#define ST_PLAYING
Usual state.
Definition: define.h:577
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:97
#define NDI_DK_ORANGE
DarkOrange2.
Definition: newclient.h:227
char * host
Which host it is connected from (ip address).
Definition: newserver.h:110
uint16_t temp_animation_id
An index into the temporary animation array.
Definition: object.h:419
uint8_t casting_time
It takes awhile to cast a spell.
Definition: global.h:268
uint8_t recycle_tmp_maps
Re-use tmp maps.
Definition: global.h:270
uint16_t emergency_y
Coordinates to use on that map.
Definition: global.h:298
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
void check_active_maps(void)
Finds maps in memory to reset.
Definition: swap.c:195
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
int cmd_shutdown_time
Time, in seconds from epoch, of server shutdown.
Definition: c_wiz.c:43
object * active_objects
List of active objects that need to be processed.
Definition: object.c:62
void free_all_newserver(void)
Free&#39;s all the memory that ericserver allocates.
Definition: init.c:395
uint32_t ticks_played
How many ticks this player has played.
Definition: player.h:203
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:475
void map_newmap_cmd(socket_struct *ns)
Sound related function.
Definition: request.c:615
int forbid_play(void)
Checks if server should be started.
Definition: server.c:1241
char * name
Name of map as given by its creator.
Definition: map.h:328
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
static void server_check_shutdown(void)
Periodically check if we&#39;re ready to shut the server down.
Definition: server.c:1289
void flush_old_maps(void)
Removes tmp-files of maps which are going to be reset next time they are visited. ...
Definition: swap.c:294
void free_loader(void)
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:379
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.c:394
#define EVENT_MAPENTER
A player entered a map.
Definition: plugin.h:90
void write_todclock(void)
Write out the current time to the file so time does not reset every time the server reboots...
Definition: init.c:446
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.c:1037
static char * clean_path(const char *file, char *newpath, int size)
Takes a path and replaces all / with _ We do a strcpy so that we do not change the original string...
Definition: server.c:304
void accounts_save(void)
Save all the account information.
Definition: account.c:267
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
static void enter_fixed_template_map(object *pl, object *exit_ob)
The player is trying to enter a non-randomly generated template map.
Definition: server.c:425
uint32_t unique
If set, this is a per player unique map.
Definition: map.h:337
void free_all_treasures(void)
Free all treasure-related memory.
Definition: treasure.c:1597
A real, living creature.
Definition: object.h:200
#define MSG_TYPE_ADMIN_PLAYER
Player coming/going/death.
Definition: newclient.h:474
unsigned long todtick
Ingame time.
Definition: init.c:440
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
static void enter_random_template_map(object *pl, object *exit_ob)
The player is trying to enter a randomly generated template map.
Definition: server.c:518
#define snprintf
Definition: win32.h:46
struct obj * active_prev
Previous object in the &#39;active list This is used in process_events so that the entire object list doe...
Definition: object.h:283
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can&#39;t fit in the given spot.
Definition: map.c:489
void free_all_anim(void)
Clears all animation-related memory.
Definition: anim.c:30
void server_main(int argc, char *argv[])
Server main function.
Definition: server.c:1390
object * transport
Transport the player is in.
Definition: player.h:195
#define MAP_TIMEOUT(m)
Definition: map.h:66
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.c:172
Control golem.
Definition: player.h:21
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
const char * name
The name of the object, obviously...
Definition: object.h:311
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:98
struct obj * env
Pointer to the object which is the environment.
Definition: object.h:293
struct quest_definition * next
Next quest in the definition list.
Definition: quest.c:89
uint8_t state
How the object was last drawn (animation)
Definition: object.h:349
int execute_global_event(int eventcode,...)
Definition: main.c:369
#define EXIT_PATH(xyz)
Definition: define.h:455
uint8_t state
Input state of the player (name, password, etc).
Definition: player.h:118
#define INS_NO_WALK_ON
Don&#39;t call check_walk_on against the originator.
Definition: object.h:570
static void process_players1(void)
Do all player-related stuff before objects have been updated.
Definition: server.c:831
int16_t last_grace
As last_sp, except for grace.
Definition: object.h:359
#define MAP_MAXTIMEOUT
MAP_MAXTIMEOUT tells the maximum of ticks until a map is swapped out after a player has left it...
Definition: config.h:408
int8_t direction
Means the object is moving that way.
Definition: object.h:334
void pets_remove_all(void)
This function checks all pets so they try to follow their master around the world.
Definition: pets.c:257
#define MAP_ENTER_Y(m)
Default Y coordinate for map enter.
Definition: map.h:87
static char * unclean_path(const char *src, char *newpath, int size)
Takes a path and replaces all _ with / This basically undoes clean_path().
Definition: server.c:332
void hiscore_check(object *op, int quiet)
Checks if player should enter the hiscore, and if so writes her into the list.
Definition: hiscore.c:302
EXTERN long nroferrors
If it exceeds MAX_ERRORS, call fatal()
Definition: global.h:136
#define SIZEOFFREE
Definition: define.h:154
int bRunning
Will be set to FALSE when the server should stop running because the service is turned off...
Definition: win32.c:159
uint16_t emergency_x
Definition: global.h:298
#define EXIT_X(xyz)
Definition: define.h:457
uint32_t has_hit
If set, weapon_sp instead of speed will count.
Definition: player.h:129
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:208
void free_globals(void)
Cleans all memory allocated for global variables.
Definition: init.c:326
void process_events(void)
Process all active objects.
Definition: server.c:967
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
void tick_the_clock(void)
This performs the basic function of advancing the clock one tick forward.
Definition: weather.c:96
float speed
The overall speed of this object.
Definition: object.h:328
int process_object(object *op)
Main object move function.
Definition: time.c:767
void init(int argc, char **argv)
This is the main server initialization function.
Definition: init.c:978
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
void cleanupPlugins(void)
Call the crossfire_plugin::closefunc on the various plugins, used at server shutdown.
Definition: plugins.c:4775
void fix_luck(void)
Fixes luck of players, slowly move it towards 0.
Definition: player.c:3891
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
void clean_tmp_files(void)
Remove temporary map files.
Definition: server.c:1105
#define MAP_MINTIMEOUT
At least that many ticks before swapout.
Definition: config.h:410
uint32_t golem_count
To track the golem.
Definition: player.h:106
void knowledge_process_incremental(void)
Incrementally send knowledge information to players, and remove information for players who left...
Definition: knowledge.c:1447
#define EXIT_Y(xyz)
Definition: define.h:458
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
struct obj * active_next
Next object in the &#39;active&#39; list This is used in process_events so that the entire object list does n...
Definition: object.h:279
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
int16_t x
Definition: object.h:326
void free_all_images(void)
Deallocates memory allocated by read_bmap_names() and read_smooth().
Definition: image.c:396
void free_all_archs(void)
Frees all memory allocated to archetypes.
Definition: arch.c:287
int32_t last_eat
How long since we last ate.
Definition: object.h:356
int Ysize
Definition: random_map.h:70
int handle_newcs_player(object *op)
Handles commands the player can send us, and various checks on invisibility, golem and such...
Definition: player.c:3092
Path-related function prototypes.
void free_all_artifacts(void)
Free all artifact-related information.
Definition: artifact.c:140
const char * confdir
Configuration files.
Definition: global.h:243
static const flag_definition flags[]
Flag mapping.
int Xsize
Definition: random_map.h:69
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.c:186
int save_map(mapstruct *m, int flag)
Saves a map to file.
Definition: map.c:1436
void free_all_recipes(void)
Frees all memory allocated to recipes and recipes lists.
Definition: recipe.c:745
object * ob
The object representing the player.
Definition: player.h:158
int32_t timeout
Swapout is set to this.
Definition: map.h:341
char origin_map[RM_SIZE]
Path to the map this random map is generated from, to make an exit back.
Definition: random_map.h:50
#define EVENT_CLOCK
Global time event.
Definition: plugin.h:84
See Player.
Definition: object.h:107
static char const * crypt_string(char const str[static 1], char const *salt)
Encrypt a string.
Definition: server.c:64
char killer[BIG_NAME]
Who killed this player.
Definition: player.h:171
void replace(const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
Replace in string src all occurrences of key by replacement.
Definition: utils.c:353
Object structure, the core of Crossfire.
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:342
int set_random_map_variable(RMParms *rp, const char *buf)
#define RANDOM()
Definition: define.h:679
void sleep_delta(void)
Sleep until the next tick.
Definition: time.c:180
#define PORTAL_DESTINATION_NAME
#define MAP_PLAYER_UNIQUE
This map is player-specific.
Definition: map.h:97
const char * localdir
Read/write data files.
Definition: global.h:245
void party_obsolete_parties(void)
Remove unused parties (no players), this could be made to scale a lot better.
Definition: party.c:236
int origin_y
Definition: random_map.h:83
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
struct archt * arch
Pointer to archetype.
Definition: object.h:412
#define MAP_WIDTH(m)
Map width.
Definition: map.h:78
Only for debugging purposes.
Definition: logger.h:13
unsigned int distance
Distance, in squares.
Definition: map.h:381
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
static void enter_map(object *op, mapstruct *newmap, int x, int y)
Moves the player and pets from current map (if any) to new map.
Definition: server.c:159
struct regiondef * region
Definition: random_map.h:91
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.c:679
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
int out_of_map(mapstruct *m, int x, int y)
this returns TRUE if the coordinates (x,y) are out of map m.
Definition: map.c:2294
void free_all_readable(void)
Free all readable-related information.
Definition: readable.c:2101
#define SIZEOFFREE2
Definition: define.h:153
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: main.c:261
void cftimer_process_timers(void)
Processes all timers.
Definition: timers.c:44
const char * msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:322
int16_t casting_time
Time left before spell goes off.
Definition: object.h:402
void write_book_archive(void)
Write out the updated book archive to bookarch file.
Definition: readable.c:2150
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
EXTERN player * first_player
First player.
Definition: global.h:117
struct pl * next
Pointer to next player, NULL if this is last.
Definition: player.h:93
static const char * days[]
Ingame days.
Definition: server.c:47
void initPlugins(void)
Plugins initialization.
Definition: plugins.c:4725
void free_style_maps(void)
Frees cached style maps.
Definition: style.c:309
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_...
Definition: map.c:302
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
#define SIZEOFFREE1
Definition: define.h:152
void watchdog(void)
char maplevel[MAX_BUF]
On which level is the player?
Definition: player.h:96
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
void free_all_god(void)
Frees all god information.
Definition: holy.c:337
void free_knowledge(void)
Free all knowledge data.
Definition: knowledge.c:1288
struct mapdef * next
Next map, linked list.
Definition: map.h:326
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.c:3415
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:625
char * emergency_mapname
Map to return players to in emergency.
Definition: global.h:297
This is a game-map.
Definition: map.h:325
void set_map_timeout(mapstruct *oldmap)
Applies the map timeout.
Definition: server.c:271
#define ST_GET_NAME
Player just connected.
Definition: define.h:582
void free_server(void)
Frees all memory allocated around here:
Definition: init.c:1018
#define FLAG_UNIQUE
Item is really unique (UNIQUE_ITEMS)
Definition: define.h:288
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.c:1861
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
From map.c This is used by get_player to determine where the other creature is.
Definition: map.c:2516
int origin_x
Definition: random_map.h:84
void create_template_pathname(const char *name, char *buf, size_t size)
same as create_pathname(), but for the template maps.
Definition: map.c:145
int8_t facing
Object is oriented/facing that way.
Definition: object.h:335
float weapon_speed
The overall speed of this object.
Definition: object.h:330
void clean_tmp_map(mapstruct *m)
Removse the temporary file used by the map.
Definition: map.c:1954
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.c:109
EXTERN mapstruct * first_map
First map.
Definition: global.h:118
#define PTICKS_PER_CLOCK
Definition: tod.h:9
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.c:1129
sstring followed_player
Player the DM is following.
Definition: player.h:199
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
#define P_NO_CLERIC
No clerical spells cast here.
Definition: map.h:238
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
bool check_password(const char *typed, const char *crypted)
Hash a password and compare it to the stored version.
Definition: server.c:100
#define ST_GET_PASSWORD
Name entered, now for password.
Definition: define.h:583
static void process_players2(void)
Do all player-related stuff after objects have been updated.
Definition: server.c:941
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
uint32_t count
Any numbers typed before a command.
Definition: player.h:109
Definition: object.h:224