Crossfire Server, Trunk  1.75.0
server.cpp
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 #include "server.h"
46 
48 static const int shutdown_warn_times[] = {120, 90, 60, 45, 30, 15, 10, 5, 4, 3, 2, 1};
49 
51 static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
52 
53 volatile sig_atomic_t shutdown_flag;
54 
70 static char const* crypt_string(char const *str, char const* salt) {
71 #if defined(WIN32)
72  // Windows will never attempt to crypt()
73  return str;
74 #else
75 #if (defined(__FreeBSD__))
76  // If legacy mode is enabled, do not crypt() on FreeBSD
77  if (settings.crypt_mode == 0) {
78  return str;
79  }
80 #endif
81  char s[3];
82 
83  if (salt == NULL) {
84  /* Generate a two-character salt for the DES cipher.
85  * We want the salt to be in this character set.
86  */
87  static const char *const c =
88  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
89  s[0] = c[RANDOM()%(int)strlen(c)],
90  s[1] = c[RANDOM()%(int)strlen(c)];
91  } else {
92  s[0] = salt[0],
93  s[1] = salt[1];
94  }
95  s[2] = '\0';
96 
97  return crypt(str, s);
98 #endif
99 }
100 
101 char const* newhash(char const *password) {
102  return crypt_string(password, NULL);
103 }
104 
114 bool check_password(const char *typed, const char *crypted) {
115  if (getenv("CF_DEBUG_BYPASS_LOGIN")) {
116  return true;
117  }
118 
119  // An empty hashed password only matches an empty input password.
120  if (strlen(crypted) == 0) {
121  return strlen(typed) == 0 ? true : false;
122  }
123 
124  const char *typed_hashed = crypt_string(typed, crypted);
125  if (typed_hashed != NULL) {
126  return strcmp(typed_hashed, crypted) == 0;
127  } else {
128  LOG(llevError, "Could not check password with stored hash %s\n", crypted);
129  return false;
130  }
131 }
132 
142 void enter_player_savebed(object *op) {
143  mapstruct *oldmap = op->map;
144  object *tmp;
145 
146  tmp = object_new();
147 
148  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
149  EXIT_X(tmp) = op->contr->bed_x;
150  EXIT_Y(tmp) = op->contr->bed_y;
151  enter_exit(op, tmp);
152  /* If the player has not changed maps and the name does not match
153  * that of the savebed, his savebed map is gone. Lets go back
154  * to the emergency path. Update what the players savebed is
155  * while we're at it.
156  */
157  if (oldmap == op->map && strcmp(op->contr->savebed_map, oldmap->path)) {
158  LOG(llevDebug, "Player %s savebed location %s is invalid - going to emergency location (%s)\n",
164  EXIT_PATH(tmp) = add_string(op->contr->savebed_map);
165  EXIT_X(tmp) = op->contr->bed_x;
166  EXIT_Y(tmp) = op->contr->bed_y;
167  enter_exit(op, tmp);
168  }
170 }
171 
183 static void enter_map(object *op, mapstruct *newmap, int x, int y) {
184  mapstruct *oldmap = op->map;
185 
186  /* Default hp/sp for exits changed to -1 to use enter_x/enter_y values by default, but if one value
187  * is specified, we want the other to default to zero like before the change.
188  */
189  if (x < 0 && y >= 0) x=0;
190  if (y < 0 && x >= 0) y=0;
191 
192  if (out_of_map(newmap, x, y)) {
193  if (x != -1 || y != -1) {
194  LOG(llevError, "enter_map: supplied coordinates are not within the map! (%s: %d, %d)\n", newmap->path, x, y);
195  }
196  /* If op has invalid (probably -1,-1) coordinates, force them to a correct value, else issues later on. */
197  if (op->x == x)
198  op->x = MAP_ENTER_X(newmap);
199  if (op->y == y)
200  op->y = MAP_ENTER_Y(newmap);
201  x = MAP_ENTER_X(newmap);
202  y = MAP_ENTER_Y(newmap);
203  if (out_of_map(newmap, x, y)) {
204  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));
206  "The exit is closed");
207  return;
208  }
209  }
210  /* try to find a spot for the player */
211  if (ob_blocked(op, newmap, x, y)) { /* First choice blocked */
212  /* We try to find a spot for the player, starting closest in.
213  * We could use object_find_first_free_spot(), but that doesn't randomize it at all,
214  * So for example, if the north space is free, you would always end up there even
215  * if other spaces around are available.
216  * Note that for the second and third calls, we could start at a position other
217  * than one, but then we could end up on the other side of walls and so forth.
218  */
219  int i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE1+1);
220  if (i == -1) {
221  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE2+1);
222  if (i == -1)
223  i = object_find_free_spot(op, newmap, x, y, 1, SIZEOFFREE);
224  }
225  if (i != -1) {
226  x += freearr_x[i];
227  y += freearr_y[i];
228  } else {
229  /* not much we can do in this case. */
230  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);
231  }
232  } /* end if looking for free spot */
233 
234  /* If it is a player login, he has yet to be inserted anyplace.
235  * otherwise, we need to deal with removing the playe here.
236  */
237  if (!QUERY_FLAG(op, FLAG_REMOVED))
238  object_remove(op);
239  /* object_remove clears these so they must be reset after the object_remove() call */
240  object_insert_in_map_at(op, newmap, NULL, INS_NO_WALK_ON, x, y);
241 
242  object_set_enemy(op, NULL);
243 
244  if (op->contr) {
245  safe_strncpy(op->contr->maplevel, newmap->path,
246  sizeof(op->contr->maplevel));
247  op->contr->count = 0;
248  }
249 
250  /* Update any golems */
251  if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL) {
252  int i = object_find_free_spot(op->contr->ranges[range_golem], newmap, x, y, 1, SIZEOFFREE);
254  if (i == -1) {
257  op->contr->ranges[range_golem] = NULL;
258  op->contr->golem_count = 0;
259  } else {
260  object_insert_in_map_at(op->contr->ranges[range_golem], newmap, NULL, 0, x+freearr_x[i], y+freearr_y[i]);
262  }
263  }
264  op->direction = 0;
265 
266  /* since the players map is already loaded, we don't need to worry
267  * about pending objects.
268  */
269  pets_attempt_follow(op, 1);
270 
271  /* If the player is changing maps, we need to do some special things
272  * Do this after the player is on the new map - otherwise the force swap of the
273  * old map does not work.
274  */
275  if (oldmap != newmap) {
276  player_map_change_common(op, oldmap, newmap);
277  }
278 
280 }
281 
282 void player_map_change_common(object* op, mapstruct* const oldmap,
283  mapstruct* const newmap) {
284  if (oldmap != NULL) {
286 
287  /* can be less than zero due to errors in tracking this */
288  if (oldmap->players <= 0) {
289  set_map_timeout(oldmap);
290  }
291  }
292 
294  newmap->timeout = 0;
296 }
297 
305 void set_map_timeout(mapstruct *oldmap) {
306  oldmap->timeout = MAP_MINTIMEOUT;
307 }
308 
322 static char *clean_path(const char *file, char *newpath, int size) {
323  char *cp;
324 
325  strlcpy(newpath, file, size);
326  for (cp = newpath; *cp != '\0'; cp++) {
327  if (*cp == '/')
328  *cp = '_';
329  }
330  return newpath;
331 }
332 
350 static char *unclean_path(const char *src, char *newpath, int size) {
351  char *cp;
352 
353  cp = const_cast<char *>(strrchr(src, '/'));
354  if (cp)
355  strlcpy(newpath, cp+1, size);
356  else
357  strlcpy(newpath, src, size);
358 
359  for (cp = newpath; *cp != '\0'; cp++) {
360  if (*cp == '_')
361  *cp = '/';
362  }
363  return newpath;
364 }
365 
375 static void enter_random_map(object *pl, object *exit_ob) {
376  mapstruct *new_map;
377  char newmap_name[HUGE_BUF], buf[HUGE_BUF], *cp;
378  static int reference_number = 0;
379  RMParms rp;
380 
381  memset(&rp, 0, sizeof(RMParms));
382  rp.Xsize = -1;
383  rp.Ysize = -1;
384  rp.region = get_region_by_map(exit_ob->map);
385  if (exit_ob->msg)
386  set_random_map_variable(&rp, exit_ob->msg);
387  rp.origin_x = exit_ob->x;
388  rp.origin_y = exit_ob->y;
389  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
390 
391  /* If we have a final_map, use it as a base name to give some clue
392  * as where the player is. Otherwise, use the origin map.
393  * Take the last component (after the last slash) to give
394  * shorter names without bogus slashes.
395  */
396  if (rp.final_map[0]) {
397  cp = strrchr(rp.final_map, '/');
398  if (!cp)
399  cp = rp.final_map;
400  } else {
401  cp = strrchr(rp.origin_map, '/');
402  if (!cp)
403  cp = rp.origin_map;
404  /* Need to strip of any trailing digits, if it has them */
405  strlcpy(buf, cp, sizeof(buf));
406  while (isdigit(buf[strlen(buf)-1]))
407  buf[strlen(buf)-1] = 0;
408  cp = buf;
409  }
410 
411  snprintf(newmap_name, sizeof(newmap_name), "/random/%s%04d", cp+1, reference_number++);
412 
413  /* now to generate the actual map. */
414  new_map = generate_random_map(newmap_name, &rp, NULL, exit_ob->map ? exit_ob->map->reset_group : NULL);
415 
416  /* Update the exit_ob so it now points directly at the newly created
417  * random maps. Not that it is likely to happen, but it does mean that a
418  * exit in a unique map leading to a random map will not work properly.
419  * It also means that if the created random map gets reset before
420  * the exit leading to it, that the exit will no longer work.
421  */
422  if (new_map) {
423  int x, y;
424 
425  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
426  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
427  EXIT_PATH(exit_ob) = add_string(newmap_name);
428  strlcpy(new_map->path, newmap_name, sizeof(new_map->path));
429  enter_map(pl, new_map, x, y);
430 
431  /* Make the initial map part of the same reset group so it doesn't
432  * reset before the random maps */
433  if (exit_ob->map && exit_ob->map->reset_group == NULL && new_map->reset_group && rp.link_source_map) {
434  exit_ob->map->reset_group = add_string(new_map->reset_group);
435  }
436  }
437 }
438 
448 static void enter_fixed_template_map(object *pl, object *exit_ob) {
449  mapstruct *new_map;
450  char tmpnum[32], exitpath[HUGE_BUF], resultname[HUGE_BUF], tmpstring[HUGE_BUF], *sourcemap;
451  char sourcemap_buf[HUGE_BUF];
452  char new_map_name[MAX_BUF];
453 
454  /* Split the exit path string into two parts, one
455  * for where to store the map, and one for were
456  * to generate the map from.
457  */
458  strlcpy(exitpath, EXIT_PATH(exit_ob)+2, sizeof(exitpath));
459  sourcemap = strchr(exitpath, '!');
460  if (!sourcemap) {
463  "The %s is closed.",
464  exit_ob->name);
465  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);
466  return;
467  }
468  *sourcemap++ = '\0';
469 
470  /* If we are not coming from a template map, we can use relative directories
471  * for the map to generate from.
472  */
473  if (!exit_ob->map->is_template) {
474  /* We can't use exitpath directly, as sourcemap points there. */
475  path_combine_and_normalize(exit_ob->map->path, sourcemap, sourcemap_buf, sizeof(sourcemap_buf));
476  sourcemap = sourcemap_buf;
477  }
478 
479  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
480  * of the exit, and the name of the map the exit is on, respectively.
481  */
482  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
483  replace(exitpath, "%x", tmpnum, resultname, sizeof(resultname));
484 
485  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
486  strlcpy(tmpstring, resultname, sizeof(tmpstring));
487  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
488 
489  strlcpy(tmpstring, resultname, sizeof(tmpstring));
490  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
491 
492  /* If we are coming from another template map, use reletive paths unless
493  * indicated otherwise.
494  */
495  if (exit_ob->map->is_template && (resultname[0] != '/')) {
496  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
497  } else {
498  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
499  }
500 
501  /* Attempt to load the map, if unable to, then
502  * create the map from the template.
503  */
504  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
505  if (!new_map) {
506  char path[MAX_BUF];
507  create_pathname(sourcemap, path, MAX_BUF);
508  new_map = mapfile_load(path, MAP_PLAYER_UNIQUE);
509  if (!new_map) {
511  MSG_TYPE_COMMAND_FAILURE, "The %s is closed.",
512  exit_ob->name);
513  LOG(llevError,
514  "Template exit in '%s' (%d, %d) does not reference a valid "
515  "template. Make sure a template exists at '%s'.\n",
516  exit_ob->map->path, exit_ob->x, exit_ob->y, path);
517  return;
518  }
519  }
520 
521  assert(new_map);
522  /* set the path of the map to where it should be
523  * so we don't just save over the source map.
524  */
525  strlcpy(new_map->path, new_map_name, sizeof(new_map->path));
526  new_map->is_template = 1;
527  enter_map(pl, new_map, EXIT_X(exit_ob), EXIT_Y(exit_ob));
528 }
529 
539 static void enter_random_template_map(object *pl, object *exit_ob) {
540  mapstruct *new_map;
541  char tmpnum[32], resultname[HUGE_BUF], tmpstring[HUGE_BUF];
542  char new_map_name[MAX_BUF];
543  RMParms rp;
544 
545  /* Do replacement of %x, %y, and %n to the x coord of the exit, the y coord
546  * of the exit, and the name of the map the exit is on, respectively.
547  */
548  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->x);
549  replace(EXIT_PATH(exit_ob)+3, "%x", tmpnum, resultname, sizeof(resultname));
550 
551  snprintf(tmpnum, sizeof(tmpnum), "%d", exit_ob->y);
552  strlcpy(tmpstring, resultname, sizeof(tmpstring));
553  replace(tmpstring, "%y", tmpnum, resultname, sizeof(resultname));
554 
555  strlcpy(tmpstring, resultname, sizeof(tmpstring));
556  replace(tmpstring, "%n", exit_ob->map->name, resultname, sizeof(resultname));
557 
558  /* If we are coming from another template map, use reletive paths unless
559  * indicated otherwise.
560  */
561  if (exit_ob->map->is_template && (resultname[0] != '/')) {
562  path_combine_and_normalize(exit_ob->map->path, resultname, new_map_name, sizeof(new_map_name));
563  } else {
564  create_template_pathname(resultname, new_map_name, sizeof(new_map_name));
565  }
566 
567  new_map = ready_map_name(new_map_name, MAP_PLAYER_UNIQUE);
568  if (!new_map) {
569  memset(&rp, 0, sizeof(RMParms));
570  rp.Xsize = -1;
571  rp.Ysize = -1;
572  rp.region = get_region_by_map(exit_ob->map);
573  if (exit_ob->msg)
574  set_random_map_variable(&rp, exit_ob->msg);
575  rp.origin_x = exit_ob->x;
576  rp.origin_y = exit_ob->y;
577  safe_strncpy(rp.origin_map, pl->map->path, sizeof(rp.origin_map));
578 
579  /* now to generate the actual map. */
580  new_map = generate_random_map(new_map_name, &rp, NULL, exit_ob->map ? exit_ob->map->reset_group : NULL);
581  }
582 
583  /* Update the exit_ob so it now points directly at the newly created
584  * random maps. Not that it is likely to happen, but it does mean that a
585  * exit in a unique map leading to a random map will not work properly.
586  * It also means that if the created random map gets reset before
587  * the exit leading to it, that the exit will no longer work.
588  */
589  if (new_map) {
590  int x, y;
591 
592  x = EXIT_X(exit_ob) = MAP_ENTER_X(new_map);
593  y = EXIT_Y(exit_ob) = MAP_ENTER_Y(new_map);
594  new_map->is_template = 1;
595  enter_map(pl, new_map, x, y);
596  }
597 }
598 
607 static void enter_unique_map(object *op, object *exit_ob) {
608  char apartment[2 * HUGE_BUF], path[MAX_BUF];
609  mapstruct *newmap;
610  const char* player = op->name;
611  if (op->contr->followed_player) {
613  }
614 
615  if (EXIT_PATH(exit_ob)[0] == '/') {
616  snprintf(apartment, sizeof(apartment), "~%s/%s", player, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
617  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
618  if (!newmap) {
619  newmap = mapfile_load(EXIT_PATH(exit_ob), 0);
620  }
621  } else { /* relative directory */
622  char reldir[HUGE_BUF], tmpc[HUGE_BUF], *cp;
623 
624  if (exit_ob->map->unique) {
625  // Use player's current map path to construct base of relative path in 'src'
626  char* src = strdup(op->map->path);
627  char* slash = strrchr(src, '/');
628  if (slash == NULL) {
629  abort();
630  }
631  *slash = '\0';
632 
633  unclean_path(exit_ob->map->path, reldir, sizeof(reldir));
634 
635  /* Need to copy this over, as clean_path only has one static return buffer */
636  clean_path(reldir, tmpc, sizeof(tmpc));
637  /* Remove final component, if any */
638  if ((cp = strrchr(tmpc, '_')) != NULL)
639  *cp = 0;
640 
641  snprintf(apartment, sizeof(apartment), "%s/%s_%s", src, tmpc, clean_path(EXIT_PATH(exit_ob), path, sizeof(path)));
642 
643  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
644  if (!newmap) {
645  newmap = mapfile_load(path_combine_and_normalize(reldir, EXIT_PATH(exit_ob), tmpc, sizeof(tmpc)), 0);
646  }
647  } else {
648  /* The exit is unique, but the map we are coming from is not unique. So
649  * use the basic logic - don't need to demangle the path name
650  */
651  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
652  snprintf(apartment, sizeof(apartment), "~%s/%s", player, clean_path(reldir, path, sizeof(path)));
653  newmap = ready_map_name(apartment, MAP_PLAYER_UNIQUE);
654  if (!newmap) {
655  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), reldir, sizeof(reldir));
656  newmap = ready_map_name(reldir, 0);
657  if (newmap)
658  apply_auto_fix(newmap);
659  }
660  }
661  }
662 
663  if (newmap) {
664  strlcpy(newmap->path, apartment, sizeof(newmap->path));
665  newmap->unique = 1;
666  enter_map(op, newmap, EXIT_X(exit_ob), EXIT_Y(exit_ob));
667  } else {
670  "The %s is closed.",
671  exit_ob->name);
672  /* Perhaps not critical, but I would think that the unique maps
673  * should be new enough this does not happen. This also creates
674  * a strange situation where some players could perhaps have visited
675  * such a map before it was removed, so they have the private
676  * map, but other players can't get it anymore.
677  */
678  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);
679  }
680 }
681 
682 void enter_player_maplevel(object *op) {
683  assert(op != NULL);
684  int flags = 0, x = op->x, y = op->y;
685  mapstruct *newmap;
686 
687  assert(op->type == PLAYER);
688 
689  /* newmap returns the map (if already loaded), or loads it for us. */
690  newmap = ready_map_name(op->contr->maplevel, flags);
691  if (!newmap) {
693  x = settings.emergency_x;
694  y = settings.emergency_y;
695  if (!newmap) {
696  LOG(llevError, "Fatal: Could not load emergency map!\n");
697  abort();
698  }
699 
701  "You find yourself somewhere unexpected...");
702  }
703 
704  /* as a special case, if coordinates are (-1, -1), then the item should
705  * be put at the default location. Used for loginmethod 0 (old clients). */
706  if (x == -1 && y == -1) {
707  x = MAP_ENTER_X(newmap);
708  y = MAP_ENTER_Y(newmap);
709  }
710 
711  enter_map(op, newmap, x, y);
712 }
713 
727 void enter_exit(object *op, object *exit_ob) {
728 #define PORTAL_DESTINATION_NAME "Town portal destination" /* this one should really be in a header file */
729  /* It may be nice to support other creatures moving across
730  * exits, but right now a lot of the code looks at op->contr,
731  * so thta is an RFE.
732  */
733  if (op->type != PLAYER)
734  return;
735 
736  assert(exit_ob != NULL);
737  assert(EXIT_PATH(exit_ob) != NULL);
738 
739  /* Don't word-of-recall out of a shop */
740  if ( exit_ob->subtype == SP_WORD_OF_RECALL ) {
741  /* Scan inventory for unpaid objects */
742  object *item = op->inv;
744  if (QUERY_FLAG(item, FLAG_UNPAID)) {
745  char buf[MAX_BUF];
746 
747  ob_describe(item, op, 1, buf, sizeof(buf));
749  "You feel a force fizzling away. You feel a vibration from: %s",buf);
750  return;
751  }
753  }
754 
755  /* Need to remove player from transport */
756  if (op->contr->transport)
757  ob_apply(op->contr->transport, op, AP_UNAPPLY);
758 
759  /* check to see if we make a template map
760  * Template maps have an EXIT_PATH in the form:
761  * /@[!]<MAP_NAME>!<TEMPLATE_PATH>
762  *
763  * <MAP_NAME> is the name of the destination map, which is saved in LOCALDIR/template-maps/.
764  * <TEMPLATE_PATH> is the path to a template map, used when <MAP_NAME> does not exist.
765  */
766  if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '@') {
767  if (EXIT_PATH(exit_ob)[2] == '!') {
768  /* generate a template map randomly */
769  enter_random_template_map(op, exit_ob);
770  } else {
771  /* generate a template map from a fixed template */
772  enter_fixed_template_map(op, exit_ob);
773  }
774  }
775  /* check to see if we make a randomly generated map */
776  else if (EXIT_PATH(exit_ob) && EXIT_PATH(exit_ob)[1] == '!') {
777  enter_random_map(op, exit_ob);
778  } else if (QUERY_FLAG(exit_ob, FLAG_UNIQUE)) {
779  enter_unique_map(op, exit_ob);
780  } else {
781  int x = EXIT_X(exit_ob), y = EXIT_Y(exit_ob);
782  /* 'Normal' exits that do not do anything special
783  * Simple enough we don't need another routine for it.
784  */
785  mapstruct *newmap;
786  if (exit_ob->map) {
787  char tmp_path[HUGE_BUF];
788 
789  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), tmp_path, sizeof(tmp_path));
790  newmap = ready_map_name(tmp_path, 0);
791  /* Random map was previously generated, but is no longer about. Lets generate a new
792  * map.
793  */
794  if (!newmap && !strncmp(EXIT_PATH(exit_ob), "/random/", 8)) {
795  /* Maps that go down have a message set. However, maps that go
796  * up, don't. If the going home has reset, there isn't much
797  * point generating a random map, because it won't match the maps.
798  */
799  if (exit_ob->msg) {
800  enter_random_map(op, exit_ob);
801  } else {
804  "The %s is closed.",
805  exit_ob->name);
806  return;
807  }
808 
809  /* For exits that cause damages (like pits). Don't know if any
810  * random maps use this or not.
811  */
812  if (exit_ob->stats.dam && op->type == PLAYER)
813  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
814  return;
815  }
816  } else {
817  /* For word of recall and other force objects
818  * They contain the full pathname of the map to go back to,
819  * so we don't need to normalize it.
820  * But we do need to see if it is unique or not
821  */
822  if (map_path_unique(EXIT_PATH(exit_ob)))
823  newmap = ready_map_name(EXIT_PATH(exit_ob), MAP_PLAYER_UNIQUE);
824  else
825  newmap = ready_map_name(EXIT_PATH(exit_ob), 0);
826  }
827  if (!newmap) {
828  if (exit_ob->name)
831  "The %s is closed.",
832  exit_ob->name);
833  /* don't cry to momma if name is not set - as in tmp objects
834  * used by the savebed code and character creation */
835  return;
836  }
837 
838  if (x == -1 && y == -1) {
839  x = MAP_ENTER_X(newmap);
840  y = MAP_ENTER_Y(newmap);
841  }
842 
843  /* mids 02/13/2002 if exit is damned, update players death & WoR home-position and delete town portal */
844  if (QUERY_FLAG(exit_ob, FLAG_DAMNED)) {
845  object *tmp;
846 
847  /* remove an old force with a slaying field == PORTAL_DESTINATION_NAME */
849  if (tmp) {
850  object_remove(tmp);
852  }
853 
854  path_combine_and_normalize(exit_ob->map->path, EXIT_PATH(exit_ob), op->contr->savebed_map, sizeof(op->contr->savebed_map));
855  op->contr->bed_x = EXIT_X(exit_ob), op->contr->bed_y = EXIT_Y(exit_ob);
856  save_player(op, 1);
857  }
858 
859  enter_map(op, newmap, x, y);
860  }
861 
862  LOG(llevDebug, "%s enters %s\n", op->name, EXIT_PATH(exit_ob));
863 
864  /* For exits that cause damages (like pits) */
865  if (exit_ob->stats.dam && op->type == PLAYER)
866  hit_player(op, exit_ob->stats.dam, exit_ob, exit_ob->attacktype, 1);
867 
868  if (op->contr) {
869  object* exit_copy = object_new();
870  object_copy(exit_ob, exit_copy);
871  exit_copy->speed = 0; // Item isn't on map or in inv, but object_copy() may have added it to active list
872  object_update_speed(exit_copy);
873  exit_copy->map = exit_ob->map; // hack to set map without actually inserting
874  if (op->contr->last_exit) {
876  }
877  op->contr->last_exit = exit_copy;
878  }
879 }
880 
886 static int move_towards(object *ob, object *towards, unsigned int mindist) {
887  rv_vector rv;
888  get_rangevector(ob, towards, &rv, 0);
889  if (rv.direction != 0 && rv.distance > mindist && ob->speed_left > 0) {
890  move_player(ob, rv.direction);
891  }
892  return rv.direction;
893 }
894 
899 static bool object_on_exit(object* ob, object* exit) {
900  int x = exit->x;
901  int y = exit->y;
902  int sx, sy, sx2, sy2;
903  object_get_multi_size(exit, &sx, &sy, &sx2, &sy2);
904  return (ob->x >= x+sx2) && (ob->x <= x+sx) && (ob->y >= y+sy2) && (ob->y <= y+sy);
905 }
906 
910 static void do_follow(player *pl) {
911  assert(pl->followed_player != NULL);
913  if (followed && followed->ob && followed->ob->map) {
914  if (query_flag(pl->ob, FLAG_WIZ)) {
915  rv_vector rv;
916  if (!get_rangevector(pl->ob, followed->ob, &rv, 0) || rv.distance > 4) {
917  int space = object_find_free_spot(pl->ob, followed->ob->map, followed->ob->x, followed->ob->y, 1, 25);
918  if (space == -1) {
920  space = 0;
921  }
922  object_remove(pl->ob);
923  object_insert_in_map_at(pl->ob, followed->ob->map, NULL, 0, followed->ob->x+freearr_x[space], followed->ob->y+freearr_y[space]);
924  map_newmap_cmd(pl->socket);
926  }
927  } else {
928  if (!can_follow(pl->ob, followed)) {
930  "%s stops letting you follow them.", pl->followed_player);
932  return;
933  }
934  if (move_towards(pl->ob, followed->ob, 1)== 0 && followed->ob->contr->last_exit != NULL) {
935  // Move to and apply exit
936  object* exit = followed->ob->contr->last_exit;
937  if (!object_on_exit(pl->ob, exit)) {
938  move_towards(pl->ob, exit, 0);
939  } else {
940  enter_exit(pl->ob, exit);
941  }
942  }
943  }
944  } else {
946  "You stop following %s.", pl->followed_player);
948  }
949 }
950 
956 static void process_players1(void) {
957  int flag;
958  player *pl, *plnext;
959 
960  /* Basically, we keep looping until all the players have done their actions. */
961  for (flag = 1; flag != 0; ) {
962  flag = 0;
963  for (pl = first_player; pl != NULL; pl = plnext) {
964  plnext = pl->next; /* In case a player exits the game in handle_player() */
965 
966  if (pl->ob == NULL)
967  continue;
968 
969  /* Only do this on the first pass - what we are recording
970  * here is the number of ticks the player has been online - not
971  * how many actions/moves the player has done.
972  */
973  if (!flag) pl->ticks_played++;
974 
975  if (pl->followed_player) {
976  do_follow(pl);
977  }
978 
979  if (pl->ob->speed_left > 0) {
980  if (handle_newcs_player(pl->ob))
981  flag = 1;
982  } /* end if player has speed left */
983 
984  /* If the player is not actively playing, don't make a
985  * backup save - nothing to save anyway. Plus, the
986  * map may not longer be valid. This can happen when the
987  * player quits - they exist for purposes of tracking on the map,
988  * but don't actually reside on any actual map.
989  */
990  if (QUERY_FLAG(pl->ob, FLAG_REMOVED))
991  continue;
992 
993 #ifdef AUTOSAVE
994  /* check for ST_PLAYING state so that we don't try to save off when
995  * the player is logging in.
996  */
997  if ((pl->last_save_tick+AUTOSAVE) < pticks && pl->state == ST_PLAYING) {
998  /* Don't save the player on unholy ground. Instead, increase the
999  * tick time so it will be about 10 seconds before we try and save
1000  * again.
1001  */
1002  if (get_map_flags(pl->ob->map, NULL, pl->ob->x, pl->ob->y, NULL, NULL)&P_NO_CLERIC) {
1003  pl->last_save_tick += 100;
1004  } else {
1005  save_player(pl->ob, 1);
1006  pl->last_save_tick = pticks;
1007  hiscore_check(pl->ob, 1);
1008  }
1009  }
1010 #endif
1011  } /* end of for loop for all the players */
1012  } /* for flag */
1013  for (pl = first_player; pl != NULL; pl = pl->next) {
1014  int has_action = 1;
1015 
1016  pl->ob->weapon_speed_left += pl->ob->weapon_speed;
1017  if (pl->ob->weapon_speed_left > 1.0)
1018  pl->ob->weapon_speed_left = 1.0;
1019 
1020  pl->socket->sounds_this_tick = 0;
1021 
1022  if (settings.casting_time == TRUE) {
1023  if (pl->ob->casting_time > 0) {
1024  pl->ob->casting_time--;
1025  has_action = 0;
1026  }
1027  }
1028  /* If the character is idle (standing around resting) increase
1029  * regen rates.
1030  */
1031  if (has_action && pl->ob->speed_left > 0) {
1032  pl->ob->last_heal -= 2;
1033  pl->ob->last_sp -= 2;
1034  pl->ob->last_grace -= 2;
1035  pl->ob->last_eat += 2; /* Slow down food consumption */
1036  }
1037  do_some_living(pl->ob);
1038  }
1039 }
1040 
1048 static void process_players2(void) {
1049  player *pl;
1050 
1051  /* Then check if any players should use weapon-speed instead of speed */
1052  for (pl = first_player; pl != NULL; pl = pl->next) {
1053  /* The code that did weapon_sp handling here was out of place -
1054  * this isn't called until after the player has finished there
1055  * actions, and is thus out of place. All we do here is bounds
1056  * checking.
1057  */
1058  if (pl->has_hit) {
1059  /* This needs to be here - if the player is running, we need to
1060  * clear this each tick, but new commands are not being received
1061  * so execute_newserver_command() is never called
1062  */
1063  pl->has_hit = 0;
1064  } else if (pl->ob->speed_left > pl->ob->speed)
1065  pl->ob->speed_left = pl->ob->speed;
1066 
1067  // Send delayed buffers. This has to be here (after speed processing)
1068  // because delayed messages can still be generated as result of a FIRE
1069  // command.
1071  }
1072 }
1073 
1074 #define SPEED_DEBUG
1075 
1076 static bool object_in_icecube(object *op) {
1077  return op->env != NULL && strcmp(op->env->arch->name, "icecube") == 0;
1078 }
1079 
1083 void process_events(void) {
1084  object *op;
1085  object marker;
1086  tag_t tag;
1087 
1088  process_players1();
1089 
1090  memset(&marker, 0, sizeof(object));
1091  /* Put marker object at beginning of active list */
1092  marker.active_next = active_objects;
1093 
1094  if (marker.active_next)
1095  marker.active_next->active_prev = &marker;
1096  marker.active_prev = NULL;
1097  active_objects = &marker;
1098 
1099  while (marker.active_next) {
1100  op = marker.active_next;
1101  tag = op->count;
1102 
1103  /* Move marker forward - swap op and marker */
1104  op->active_prev = marker.active_prev;
1105 
1106  if (op->active_prev)
1107  op->active_prev->active_next = op;
1108  else
1109  active_objects = op;
1110 
1111  marker.active_next = op->active_next;
1112 
1113  if (marker.active_next)
1114  marker.active_next->active_prev = &marker;
1115  marker.active_prev = op;
1116  op->active_next = &marker;
1117 
1118  /* Now process op */
1119  if (QUERY_FLAG(op, FLAG_FREED)) {
1120  LOG(llevError, "BUG: process_events(): Free object on list\n");
1121  op->speed = 0;
1122  object_update_speed(op);
1123  continue;
1124  }
1125 
1126  /* I've seen occasional crashes due to this - the object is removed,
1127  * and thus the map it points to (last map it was on) may be bogus
1128  * The real bug is to try to find out the cause of this - someone
1129  * is probably calling object_remove() without either an insert_ob or
1130  * object_free_drop_inventory() afterwards, leaving an object dangling.
1131  * But I'd rather log this and continue on instead of crashing.
1132  * Don't remove players - when a player quits, the object is in
1133  * sort of a limbo, of removed, but something we want to keep
1134  * around.
1135  */
1136  if (QUERY_FLAG(op, FLAG_REMOVED)
1137  && op->type != PLAYER
1138  && op->map
1139  && op->map->in_memory != MAP_IN_MEMORY) {
1140  StringBuffer *sb;
1141  char *diff;
1142 
1143  LOG(llevError, "BUG: process_events(): Removed object on list\n");
1144  sb = stringbuffer_new();
1145  object_dump(op, sb);
1146  diff = stringbuffer_finish(sb);
1147  LOG(llevError, "%s\n", diff);
1148  free(diff);
1150  continue;
1151  }
1152 
1153  if (!op->speed) {
1154  LOG(llevError, "BUG: process_events(): Object %s has no speed, but is on active list\n", op->arch->name);
1155  object_update_speed(op);
1156  continue;
1157  }
1158 
1159  if (op->map == NULL
1160  && op->env == NULL
1161  && op->name
1162  && op->type != MAP) {
1163  LOG(llevError, "BUG: process_events(): Object without map or inventory is on active list: %s (%d)\n", op->name, op->count);
1164  op->speed = 0;
1165  object_update_speed(op);
1166  continue;
1167  }
1168 
1169  /* Seen some cases where process_object() is crashing because
1170  * the object is on a swapped out map. But can't be sure if
1171  * something in the chain of events caused the object to
1172  * change maps or was just never removed - this will
1173  * give some clue as to its state before call to
1174  * process_object
1175  */
1176  if (op->map && op->map->in_memory != MAP_IN_MEMORY) {
1177  LOG(llevError, "BUG: process_events(): Processing object on swapped out map: %s (%d), map=%s\n", op->name, op->count, op->map->path);
1178  }
1179 
1180  /* Animate the object. Bug of feature that andim_speed
1181  * is based on ticks, and not the creatures speed?
1182  */
1183  if ((op->anim_speed && op->last_anim >= op->anim_speed)
1184  || (op->temp_animation && op->last_anim >= op->temp_anim_speed)) {
1185  op->state++;
1186  if ((op->type == PLAYER) || (op->type == MONSTER))
1187  animate_object(op, op->facing);
1188  else
1189  animate_object(op, op->direction);
1190  op->last_anim = 1;
1191  } else {
1192  op->last_anim++;
1193  }
1194 
1195  if (op->speed_left > 0) {
1196  // Players are special because their speed_left has already been
1197  // reduced in do_server(). Players effectively process every tick
1198  // so long they have non-zero speed left.
1199  if (op->type != PLAYER) {
1200  // Objects in icecubes decay at a slower rate
1201  if (object_in_icecube(op)) {
1202  op->speed_left -= 10;
1203  } else {
1204  op->speed_left -= 1;
1205  }
1206  }
1207  process_object(op);
1208  if (object_was_destroyed(op, tag))
1209  continue;
1210  } else {
1211  // Custom-made creatures for random maps can still have negative speeds, so catch that with FABS().
1212  op->speed_left += FABS(op->speed);
1213  }
1214  if (settings.casting_time == TRUE && op->casting_time > 0)
1215  op->casting_time--;
1216  }
1217 
1218  /* Remove marker object from active list */
1219  if (marker.active_prev != NULL)
1220  marker.active_prev->active_next = NULL;
1221  else
1222  active_objects = NULL;
1223 
1224  process_players2();
1225 }
1226 
1231 void clean_tmp_files(void) {
1232  mapstruct *m, *next;
1233  for (m = first_map; m != NULL; m = next) {
1234  next = m->next;
1235  if (m->in_memory == MAP_IN_MEMORY) {
1236  // Save all maps currently in memory, because they might contain
1237  // unique tiles that have not been written to disk.
1238  if (settings.recycle_tmp_maps) {
1239  // swap_map() also updates the write log.
1240  swap_map(m);
1241  } else {
1243  // FIXME: Unfortunately, save_map() also unnecessarily saves
1244  // non-unique tiles to a new temporary file, so we have to
1245  // get rid of it here.
1246  clean_tmp_map(m);
1247  }
1248  } else {
1249  // Remove the swap file.
1250  clean_tmp_map(m);
1251  }
1252  }
1253  write_todclock(); /* lets just write the clock here */
1254 }
1255 
1257 void cleanup(void) {
1258  metaserver2_exit();
1259  LOG(llevInfo, "Cleaning up...\n");
1260  clean_tmp_files();
1262  accounts_save();
1263 
1264  close_modules();
1265 
1266 #ifdef MEMORY_DEBUG
1267  free_all_maps();
1268  free_style_maps();
1269 #endif
1270  cleanupPlugins();
1271  commands_clear();
1272 #ifdef MEMORY_DEBUG
1273  free_all_archs();
1275  free_all_images();
1277  free_all_recipes();
1279  free_all_god();
1280  free_all_anim();
1281  i18n_free();
1282  free_loader();
1283  free_globals();
1284  free_server();
1286  free_knowledge();
1287  free_quest();
1289  /* See what the string data that is out there that hasn't been freed. */
1290  /* LOG(llevDebug, "%s", ss_dump_table(0xff));*/
1291 #endif
1292  exit(0);
1293 }
1294 
1303 void leave(player *pl, int draw_exit) {
1304  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
1305  pets_terminate_all(pl->ob);
1306  object_remove(pl->ob);
1307  }
1308 
1309  pl->socket->status = Ns_Dead;
1310  LOG(llevInfo, "logout: %s from %s\n", pl->ob->name, pl->socket->host);
1311 
1312  strcpy(pl->ob->contr->killer, "left");
1313  hiscore_check(pl->ob, 1);
1314 
1315  /* If this player is the captain of the transport, need to do
1316  * some extra work. By the time we get here, object_remove()
1317  * should have already been called.
1318  */
1319  if (pl->transport && pl->transport->contr == pl) {
1320  /* If inv is a non player, inv->contr will be NULL, but that
1321  * is OK.
1322  */
1323  if (pl->transport->inv)
1324  pl->transport->contr = pl->transport->inv->contr;
1325  else
1326  pl->transport->contr = NULL;
1327 
1328  if (pl->transport->contr) {
1329  char name[MAX_BUF];
1330 
1334  "%s has left. You are now the captain of %s",
1335  pl->ob->name, name);
1336  }
1337  }
1338 
1339  if (pl->ob->map) {
1340  if (pl->ob->map->in_memory == MAP_IN_MEMORY)
1341  pl->ob->map->timeout = MAP_TIMEOUT(pl->ob->map);
1342  pl->ob->map = NULL;
1343  }
1344  pl->ob->type = DEAD_OBJECT; /* To avoid problems with inventory window */
1345  party_leave(pl->ob);
1346  /* If a hidden dm dropped connection do not create
1347  * inconsistencies by showing that they have left the game
1348  */
1349  if (!(QUERY_FLAG(pl->ob, FLAG_WIZ) && pl->ob->contr->hidden)
1350  && (draw_exit) && (pl->state != ST_GET_NAME && pl->state != ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD))
1353  "%s left the game.",
1354  pl->ob->name);
1355 }
1356 
1364 int forbid_play(void) {
1365 #if !defined(_IBMR2) && !defined(___IBMR2) && defined(PERM_FILE)
1366  char buf[MAX_BUF], day[MAX_BUF];
1367  FILE *fp;
1368  time_t clock;
1369  struct tm *tm;
1370  int i, start, stop, forbit = 0;
1371 
1372  clock = time(NULL);
1373  tm = (struct tm *)localtime(&clock);
1374 
1375  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, PERM_FILE);
1376  if ((fp = fopen(buf, "r")) == NULL)
1377  return 0;
1378 
1379  while (fgets(buf, sizeof(buf), fp)) {
1380  if (buf[0] == '#')
1381  continue;
1382  if (!strncmp(buf, "msg", 3)) {
1383  if (forbit)
1384  while (fgets(buf, sizeof(buf), fp)) /* print message */
1385  fputs(buf, logfile);
1386  break;
1387  } else if (sscanf(buf, "%s %d%*c%d\n", day, &start, &stop) != 3) {
1388  LOG(llevDebug, "Warning: Incomplete line in permission file ignored.\n");
1389  continue;
1390  }
1391 
1392  for (i = 0; i < 7; i++) {
1393  if (!strncmp(buf, days[i], 3)
1394  && (tm->tm_wday == i)
1395  && (tm->tm_hour >= start)
1396  && (tm->tm_hour < stop))
1397  forbit = 1;
1398  }
1399  }
1400 
1401  fclose(fp);
1402 
1403  return forbit;
1404 #else
1405  return 0;
1406 #endif
1407 }
1408 
1409 static void save_and_kick_all_players(void) {
1410  for (player *pl = first_player; pl != NULL; ) {
1411  player *npl = pl->next;
1412  save_player(pl->ob, 0);
1413  leave(pl, 0);
1414  final_free_player(pl);
1415  pl = npl;
1416  }
1417 }
1418 
1419 static void do_shutdown(void) {
1421  MSG_TYPE_ADMIN_DM, "The server has shut down.");
1423 
1424  // Maps are saved out in clean_tmp_files(), called by cleanup().
1425  cleanup();
1426 }
1427 
1431 static bool check_shutdown(void) {
1432  if (shutdown_flag == 1) {
1433  LOG(llevInfo, "Received SIGINT; shutting down...\n");
1434  return true;
1435  }
1436 
1438  return false;
1439  }
1440 
1442  if (count_players() == 0) {
1443  if (shutdown_state.time == 0) {
1444  // Start idle countdown
1445  shutdown_state.time = time(NULL);
1446  return false;
1447  } else {
1448  time_t diff = time(NULL) - shutdown_state.time;
1449  if (diff > 60) {
1450  LOG(llevInfo, "No active players in the last %ld seconds, shutting down...\n", diff);
1451  return true;
1452  } else {
1453  return false;
1454  }
1455  }
1456  } else {
1457  // Reset idle time, since there are players
1458  shutdown_state.time = 0;
1459  }
1460  return false;
1461  }
1462 
1463  assert(shutdown_state.type == SHUTDOWN_TIME);
1464 
1465  /* If a timed shutdown is coming, remind players periodically. */
1466  time_t time_left = shutdown_state.time - time(NULL);
1467 
1468  for (unsigned int i = shutdown_state.next_warn; i < sizeof(shutdown_warn_times) / sizeof(int); i++) {
1469  if (shutdown_warn_times[i] == (int)ceil(time_left / 60.0)) {
1472  "Server shutting down in %d minutes.", shutdown_warn_times[i]);
1473  shutdown_state.next_warn = i + 1;
1474  return false;
1475  }
1476  }
1477 
1478  if (time_left <= 0) {
1479  return true;
1480  }
1481  return false;
1482 }
1483 
1488 void login_check_shutdown(object* const op) {
1490  return;
1491  }
1492 
1496  "This server will shut down when all players leave.");
1497  return;
1498  }
1499 
1500  assert(shutdown_state.type == SHUTDOWN_TIME);
1501 
1502  time_t time_left = shutdown_state.time - time(NULL);
1503  if (time_left <= 60*shutdown_warn_times[0]) {
1506  "This server will shut down in %lu minutes.", time_left / 60);
1507  }
1508 }
1509 
1524 static void do_specials(void) {
1525  if (check_shutdown()) {
1526  do_shutdown();
1527  }
1528 
1529 #ifdef CS_LOGSTATS
1530  if ((time(NULL)-cst_lst.time_start) >= CS_LOGTIME) {
1531  write_cs_stats();
1532  }
1533 #endif
1534 
1535  if (!(pticks%10))
1537 
1538 #ifdef WATCHDOG
1539  if (!(pticks%503))
1540  watchdog();
1541 #endif
1542 
1543  if (!(pticks%PTICKS_PER_CLOCK))
1544  tick_the_clock();
1545 
1546  if (!(pticks%509))
1547  flush_old_maps(); /* Clears the tmp-files of maps which have reset */
1548 
1549  if (!(pticks%2503))
1550  fix_weight(); /* Hack to fix weightproblems caused by bugs */
1551 
1552  if (!(pticks%2521))
1553  metaserver_update(); /* 2500 ticks is about 5 minutes */
1554 
1555  if (!(pticks%2531))
1556  accounts_save();
1557 
1558  if (!(pticks%5003))
1560 
1561  if (!(pticks%5009))
1563 
1564  if (!(pticks%5011))
1566 
1567  if (!(pticks%12503))
1568  fix_luck();
1569 }
1570 
1579 void server_main(int argc, char *argv[]) {
1580  PROFILE_BEGIN();
1581 #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */
1582  _fmode = _O_BINARY;
1583 #endif
1584 
1585 #ifndef WIN32
1586  /* Here we check that we aren't root or suid */
1587  if (getuid() == 0 || geteuid() == 0) {
1588  fprintf(stderr,
1589  "Running crossfire-server as root is a bad idea; aborting!\n"
1590  "Please run it again as a normal, unprivileged user.\n");
1591  exit(EXIT_FAILURE);
1592  }
1593 #endif
1594 
1595 #ifdef DEBUG_MALLOC_LEVEL
1596  malloc_debug(DEBUG_MALLOC_LEVEL);
1597 #endif
1598 
1599  init(argc, argv);
1600  initPlugins(); /* GROS - Init the Plugins */
1601  // Give feedback that loading is complete. This prevents confusion on when it is done loading.
1602  PROFILE_END(diff, LOG(llevInfo, "Initialization complete (%ld ms). Waiting for connections.\n", diff/1000));
1603 #ifdef WIN32
1604  while (bRunning) {
1605 #else
1606  while (TRUE) {
1607 #endif
1608  nroferrors = 0;
1609 
1610  tick_game_time();
1611  do_server();
1612  process_events(); /* "do" something with objects with speed */
1613  cftimer_process_timers(); /* Process the crossfire Timers */
1615  check_active_maps(); /* Removes unused maps after a certain timeout */
1616  do_specials(); /* Routines called from time to time. */
1617  update_players();
1618  }
1619 
1620  /* This is unreachable. */
1621  abort();
1622 }
write_book_archive
void write_book_archive(void)
Write out the updated book archive to bookarch file.
Definition: readable.cpp:2005
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Checks if an object still exists.
Definition: object.h:70
Settings::casting_time
uint8_t casting_time
It takes awhile to cast a spell.
Definition: global.h:272
fix_weight
void fix_weight(void)
Check recursively the weight of all players, and fix what needs to be fixed.
Definition: player.cpp:3911
check_shutdown
static bool check_shutdown(void)
Check if we're ready to shut the server down.
Definition: server.cpp:1431
handle_newcs_player
int handle_newcs_player(object *op)
Handles commands the player can send us, and various checks on invisibility, golem and such.
Definition: player.cpp:3103
player::bed_y
int16_t bed_y
x,y - coordinates of respawn (savebed).
Definition: player.h:111
object::weapon_speed_left
float weapon_speed_left
How much speed is left to spend this round.
Definition: object.h:340
PLAYER
@ PLAYER
Definition: object.h:112
player::next
player * next
Pointer to next player, NULL if this is last.
Definition: player.h:106
path.h
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:545
i18n_free
void i18n_free(void)
Clears all i18n-related data.
Definition: languages.cpp:210
first_player
player * first_player
First player.
Definition: init.cpp:106
clean_tmp_files
void clean_tmp_files(void)
Save unique maps and clean up temporary map files unless recycling temporary maps.
Definition: server.cpp:1231
settings
struct Settings settings
Server settings.
Definition: init.cpp:139
INS_NO_WALK_ON
#define INS_NO_WALK_ON
Don't call check_walk_on against the originator.
Definition: object.h:582
random_map.h
tick_the_clock
void tick_the_clock(void)
This performs the basic function of advancing the clock one tick forward.
Definition: weather.cpp:94
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
MAP
@ MAP
Definition: object.h:130
remove_friendly_object
void remove_friendly_object(object *op)
Removes the specified object from the linked list of friendly objects.
Definition: friend.cpp:52
pets_terminate_all
void pets_terminate_all(object *owner)
Removes all pets someone owns.
Definition: pets.cpp:225
enter_player_savebed
void enter_player_savebed(object *op)
This is a basic little function to put the player back to his savebed.
Definition: server.cpp:142
ST_GET_PASSWORD
#define ST_GET_PASSWORD
Name entered, now for password.
Definition: define.h:541
send_delayed_buffers
void send_delayed_buffers(player *pl)
Send all delayed buffers for a player.
Definition: player.cpp:4530
MONSTER
@ MONSTER
A real, living creature.
Definition: object.h:205
Settings::recycle_tmp_maps
uint8_t recycle_tmp_maps
Re-use tmp maps.
Definition: global.h:274
Settings::emergency_y
uint16_t emergency_y
Coordinates to use on that map.
Definition: global.h:302
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
RMParms::origin_map
char origin_map[RM_SIZE]
Path to the map this random map is generated from, to make an exit back.
Definition: random_map.h:55
FABS
#define FABS(x)
Decstations have trouble with fabs()...
Definition: define.h:22
MSG_TYPE_ADMIN_PLAYER
#define MSG_TYPE_ADMIN_PLAYER
Player coming/going/death.
Definition: newclient.h:499
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
SHUTDOWN_IDLE
@ SHUTDOWN_IDLE
Definition: commands.h:44
PTICKS_PER_CLOCK
#define PTICKS_PER_CLOCK
Number of ticks per in-game hour.
Definition: tod.h:12
free_all_readable
void free_all_readable(void)
Free all readable-related information.
Definition: readable.cpp:1974
player
One player.
Definition: player.h:105
object_free_all_data
void object_free_all_data(void)
Destroys all allocated objects.
Definition: object.cpp:767
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
player::golem_count
uint32_t golem_count
To track the golem.
Definition: player.h:119
enter_map
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.cpp:183
ready_map_name
mapstruct * ready_map_name(const char *name, int flags)
Makes sure the given map is loaded and swapped in.
Definition: map.cpp:1780
SIZEOFFREE1
#define SIZEOFFREE1
Definition: define.h:153
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
flush_old_maps
void flush_old_maps(void)
Reset maps that need to, remove their swap file.
Definition: swap.cpp:291
ST_GET_NAME
#define ST_GET_NAME
Player just connected.
Definition: define.h:540
set_map_timeout
void set_map_timeout(mapstruct *oldmap)
Enable swapping for the given map.
Definition: server.cpp:305
Settings::crypt_mode
uint8_t crypt_mode
0 for legacy behavior, 1 for always Traditional
Definition: global.h:332
c
static event_registration c
Definition: citylife.cpp:422
object::arch
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
player::bed_x
int16_t bed_x
Definition: player.h:111
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
mapstruct::players
int16_t players
How many players are on this level right now.
Definition: map.h:334
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.cpp:915
FLAG_UNIQUE
#define FLAG_UNIQUE
Item is really unique (UNIQUE_ITEMS)
Definition: define.h:287
accounts_save
void accounts_save(void)
Save all the account information.
Definition: account.cpp:255
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:433
object::x
int16_t x
Definition: object.h:335
player::ob
object * ob
The object representing the player.
Definition: player.h:177
do_server
void do_server(void)
This checks the sockets for input and exceptions, does the right thing.
Definition: loop.cpp:524
RMParms::Ysize
int Ysize
Definition: random_map.h:75
do_follow
static void do_follow(player *pl)
Called from process_players1() to move a player who is following someone.
Definition: server.cpp:910
player::transport
object * transport
Transport the player is in.
Definition: player.h:214
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
set_random_map_variable
int set_random_map_variable(RMParms *rp, const char *buf)
Definition: reader.cpp:2526
enter_random_map
static void enter_random_map(object *pl, object *exit_ob)
The player is trying to enter a randomly generated map.
Definition: server.cpp:375
time
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
Definition: arch-handbook.txt:206
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
move_player
int move_player(object *op, int dir)
Move player in the given direction.
Definition: player.cpp:2965
free_all_newserver
void free_all_newserver(void)
Free's all the memory that ericserver allocates.
Definition: init.cpp:401
object::direction
int8_t direction
Means the object is moving that way.
Definition: object.h:344
object::count
tag_t count
Unique object number for this object.
Definition: object.h:307
flags
static const flag_definition flags[]
Flag mapping.
Definition: gridarta-types-convert.cpp:101
object::last_grace
int16_t last_grace
As last_sp, except for grace.
Definition: object.h:369
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.cpp:1192
MAP_PLAYER_UNIQUE
#define MAP_PLAYER_UNIQUE
This map is player-specific.
Definition: map.h:92
player::savebed_map
char savebed_map[MAX_BUF]
Map where player will respawn after death.
Definition: player.h:110
PROFILE_BEGIN
#define PROFILE_BEGIN(expr)
Definition: global.h:371
RMParms::origin_y
int origin_y
Definition: random_map.h:88
free_knowledge
void free_knowledge(void)
Free all knowledge data.
Definition: knowledge.cpp:1280
Settings::emergency_x
uint16_t emergency_x
Definition: global.h:302
player::hidden
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:147
generate_random_map
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout, sstring reset_group)
Main random map routine.
Definition: random_map.cpp:75
cleanupPlugins
void cleanupPlugins(void)
Call the crossfire_plugin::closefunc on the various plugins, used at server shutdown.
Definition: plugins.cpp:4618
mapstruct::is_template
uint32_t is_template
If set, this is a template map.
Definition: map.h:329
range_golem
@ range_golem
Control golem.
Definition: player.h:34
enter_player_maplevel
void enter_player_maplevel(object *op)
Move a player to its stored map level.
Definition: server.cpp:682
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:355
MSG_TYPE_MISC
#define MSG_TYPE_MISC
Messages that don't go elsewhere.
Definition: newclient.h:416
party_obsolete_parties
void party_obsolete_parties(void)
Remove unused parties (no players).
Definition: party.cpp:215
free_all_maps
void free_all_maps(void)
Frees all allocated maps.
Definition: map.cpp:1974
pticks
uint32_t pticks
Number of ticks since time reset.
Definition: time.cpp:47
buf
StringBuffer * buf
Definition: readable.cpp:1565
active_objects
object * active_objects
List of active objects that need to be processed.
Definition: object.cpp:296
initPlugins
void initPlugins(void)
Plugins initialization.
Definition: plugins.cpp:4570
hiscore_check
void hiscore_check(object *op, int quiet)
Checks if player should enter the hiscore, and if so writes her into the list.
Definition: hiscore.cpp:348
version.h
RMParms
Random map parameters.
Definition: random_map.h:14
HUGE_BUF
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
query_flag
static int query_flag(const object *op, int flag)
Definition: object.h:505
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:407
move_towards
static int move_towards(object *ob, object *towards, unsigned int mindist)
Move 'ob' in the direction of 'towards' (without any pathfinding) if the two objects are farther than...
Definition: server.cpp:886
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
Ns_Dead
@ Ns_Dead
Definition: newserver.h:67
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:500
free_loader
void free_loader(void)
Frees all memory allocated by the loader.
Definition: loader.cpp:39074
CS_Stats::time_start
time_t time_start
Definition: newclient.h:701
PROFILE_END
#define PROFILE_END(var, expr)
Definition: global.h:376
RMParms::origin_x
int origin_x
Definition: random_map.h:89
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:422
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:126
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
apply_auto_fix
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.cpp:258
login_check_shutdown
void login_check_shutdown(object *const op)
Warn op if a server shutdown is scheduled.
Definition: server.cpp:1488
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1560
shutdown_s::time
time_t time
When using SHUTDOWN_TIME, time of shutdown.
Definition: commands.h:49
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
forbid_play
int forbid_play(void)
Checks if server should be started.
Definition: server.cpp:1364
object::temp_anim_speed
uint8_t temp_anim_speed
Ticks between temporary animation-frames.
Definition: object.h:432
MAP_MINTIMEOUT
#define MAP_MINTIMEOUT
At least that many ticks before swapout.
Definition: config.h:409
write_todclock
void write_todclock(void)
Write out the current time to the file so time does not reset every time the server reboots.
Definition: init.cpp:517
final_free_player
void final_free_player(player *pl)
Sends the 'goodbye' command to the player, and closes connection.
Definition: init.cpp:453
player::killer
char killer[BIG_NAME]
Who killed this player.
Definition: player.h:190
object::last_heal
int32_t last_heal
Last healed.
Definition: object.h:367
object::subtype
uint8_t subtype
Subtype of object.
Definition: object.h:349
EVENT_CLOCK
#define EVENT_CLOCK
Global time event.
Definition: events.h:40
freearr_y
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
object::anim_speed
uint8_t anim_speed
Ticks between animation-frames.
Definition: object.h:429
clean_path
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.cpp:322
query_name
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:588
object::weapon_speed
float weapon_speed
The overall speed of this object.
Definition: object.h:339
player::followed_player
sstring followed_player
Player the DM is following.
Definition: player.h:218
player::ranges
object * ranges[range_size]
Object for each range.
Definition: player.h:116
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.cpp:172
free_all_artifacts
void free_all_artifacts(void)
Free all artifact-related information.
Definition: artifact.cpp:117
clean_friendly_list
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.cpp:80
RMParms::final_map
char final_map[RM_SIZE]
If not empty, the path of the final map this whole maze leads to.
Definition: random_map.h:57
object_dump
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.cpp:645
party_leave
void party_leave(object *op)
Makes a player leave his party.
Definition: party.cpp:123
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
EVENT_MAPENTER
#define EVENT_MAPENTER
A player entered a map.
Definition: events.h:46
first_map
mapstruct * first_map
First map.
Definition: init.cpp:107
FOR_OB_AND_BELOW_FINISH
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
Definition: define.h:748
object_get_multi_size
void object_get_multi_size(const object *ob, int *sx, int *sy, int *hx, int *hy)
Computes the size of a multitile object.
Definition: object.cpp:4744
clean_tmp_map
void clean_tmp_map(mapstruct *m)
Removse the temporary file used by the map.
Definition: map.cpp:1965
free_quest
void free_quest(void)
Free all quest status structures.
Definition: quest.cpp:891
shutdown_s::type
enum shutdown_type type
Definition: commands.h:48
object::casting_time
int16_t casting_time
Time left before spell goes off.
Definition: object.h:414
process_events
void process_events(void)
Process all active objects.
Definition: server.cpp:1083
FLAG_FREED
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
server_main
void server_main(int argc, char *argv[])
Server main function.
Definition: server.cpp:1579
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Return 1 if coordinates X and Y are out of the map M, taking into account tiling.
Definition: map.cpp:2306
socket_struct::host
char * host
Which host it is connected from (ip address).
Definition: newserver.h:100
do_specials
static void do_specials(void)
Collection of functions to call from time to time.
Definition: server.cpp:1524
PORTAL_DESTINATION_NAME
#define PORTAL_DESTINATION_NAME
object::last_eat
int32_t last_eat
How long since we last ate.
Definition: object.h:366
nroferrors
long nroferrors
If it exceeds MAX_ERRORS, call fatal()
Definition: init.cpp:112
ob_describe
char * ob_describe(const object *op, const object *observer, int use_media_tags, char *buf, size_t size)
Returns the description of an object, as seen by the given observer.
Definition: ob_methods.cpp:91
object_update_speed
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1349
object::last_anim
uint8_t last_anim
Last sequence used to draw face.
Definition: object.h:430
object_on_exit
static bool object_on_exit(object *ob, object *exit)
Return true if the player object is on the given exit.
Definition: server.cpp:899
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
enter_exit
void enter_exit(object *op, object *exit_ob)
Tries to move 'op' to exit_ob.
Definition: server.cpp:727
newhash
char const * newhash(char const *password)
Definition: server.cpp:101
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:317
living::dam
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
object::active_prev
object * active_prev
Previous object in the 'active list This is used in process_events so that the entire object list doe...
Definition: object.h:291
object_free
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1592
init
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin it tries to load all available files in the SHARE plugins directory as plugin libraries It first displays the Initializing the plugin has the opportunity to signal itself by a message on the console Then the server displays an informative message containing both the plugin content and its keyword For the Python the standard load process thus GreenGoblin When a plugin has been it can request to be warned whenever a global event and are named freely by the developer If the directory doesn t nothing will happen< event name > can be init
Definition: plugins.txt:54
tag_t
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:14
mapstruct::reset_group
sstring reset_group
For reset purpose, all maps in the same group reset at the same time.
Definition: map.h:327
rproto.h
Settings::confdir
const char * confdir
Configuration files.
Definition: global.h:249
sproto.h
logfile
FILE * logfile
Used by server/daemon.c.
Definition: init.cpp:114
FOR_OB_AND_BELOW_PREPARE
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
Definition: define.h:744
process_players1
static void process_players1(void)
Do all player-related stuff before objects have been updated.
Definition: server.cpp:956
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:414
cftimer_process_timers
void cftimer_process_timers(void)
Processes all timers.
Definition: timers.cpp:44
object_in_icecube
static bool object_in_icecube(object *op)
Definition: server.cpp:1076
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
player::maplevel
char maplevel[MAX_BUF]
On which level is the player?
Definition: player.h:109
SHUTDOWN_NONE
@ SHUTDOWN_NONE
Definition: commands.h:42
ob_blocked
int ob_blocked(const object *ob, mapstruct *m, int16_t x, int16_t y)
Returns true if the given object can't fit in the given spot.
Definition: map.cpp:491
object_insert_in_map_at
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.cpp:2100
MAP_WIDTH
#define MAP_WIDTH(m)
Map width.
Definition: map.h:73
SIZEOFFREE
#define SIZEOFFREE
Definition: define.h:155
create_template_pathname
void create_template_pathname(const char *name, char *buf, size_t size)
same as create_pathname(), but for the template maps.
Definition: map.cpp:145
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:435
shutdown_flag
volatile sig_atomic_t shutdown_flag
Definition: server.cpp:53
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
free_all_recipes
void free_all_recipes(void)
Frees all memory allocated to recipes and recipes lists.
Definition: recipe.cpp:811
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
Definition: porting.cpp:222
object_new
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it.
Definition: object.cpp:1273
free_all_god
void free_all_god(void)
Frees all god information.
Definition: holy.cpp:327
path
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
PERM_FILE
#define PERM_FILE
You can restrict playing in certain times by creating a PERMIT_FILE in CONFDIR.
Definition: config.h:454
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
SAVE_MODE_NORMAL
#define SAVE_MODE_NORMAL
No special handling.
Definition: map.h:116
RANDOM
#define RANDOM()
Definition: define.h:638
metaserver2_exit
void metaserver2_exit()
Stop metaserver updates.
Definition: metaserver.cpp:492
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:200
free_quest_definitions
void free_quest_definitions(void)
bRunning
int bRunning
enter_unique_map
static void enter_unique_map(object *op, object *exit_ob)
Player is entering a unique map.
Definition: server.cpp:607
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Failed result from command.
Definition: newclient.h:534
can_follow
bool can_follow(object *, player *)
Definition: c_wiz.cpp:2796
socket_struct::sounds_this_tick
int8_t sounds_this_tick
Number of sounds sent this tick.
Definition: newserver.h:121
player_map_change_common
void player_map_change_common(object *op, mapstruct *const oldmap, mapstruct *const newmap)
Definition: server.cpp:282
ST_PLAYING
#define ST_PLAYING
Usual state.
Definition: define.h:535
find_dir_2
int find_dir_2(int x, int y)
Computes a direction which you should travel to move of x and y.
Definition: object.cpp:3677
pets_attempt_follow
void pets_attempt_follow(object *for_owner, int force)
Check pets so they try to follow their master around the world.
Definition: pets.cpp:249
replace
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.cpp:327
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
object_find_by_type_and_slaying
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.cpp:4158
FLAG_WIZ
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
swap_map
int swap_map(mapstruct *map)
Swaps a map to disk.
Definition: swap.cpp:136
Settings::emergency_mapname
char * emergency_mapname
Map to return players to in emergency.
Definition: global.h:301
llevInfo
@ llevInfo
Information.
Definition: logger.h:12
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:265
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
player::has_hit
uint32_t has_hit
If set, weapon_sp instead of speed will count.
Definition: player.h:144
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:636
SIZEOFFREE2
#define SIZEOFFREE2
Definition: define.h:154
free_style_maps
void free_style_maps(void)
Frees cached style maps.
Definition: style.cpp:312
check_password
bool check_password(const char *typed, const char *crypted)
Hash a password and compare it to the stored version.
Definition: server.cpp:114
shutdown_warn_times
static const int shutdown_warn_times[]
How many minutes before a shutdown to warn players, in reverse order.
Definition: server.cpp:48
ST_CONFIRM_PASSWORD
#define ST_CONFIRM_PASSWORD
New character, confirm password.
Definition: define.h:542
metaserver_update
void metaserver_update(void)
Updates our info in the metaserver Note that this is used for both metaserver1 and metaserver2 - for ...
Definition: metaserver.cpp:80
get_map_flags
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.cpp:300
save_and_kick_all_players
static void save_and_kick_all_players(void)
Definition: server.cpp:1409
mapstruct
This is a game-map.
Definition: map.h:315
object::env
object * env
Pointer to the object which is the environment.
Definition: object.h:301
create_pathname
char * create_pathname(const char *name, char *buf, size_t size)
Get the full path to a map file.
Definition: map.cpp:104
write_cs_stats
void write_cs_stats(void)
SHUTDOWN_TIME
@ SHUTDOWN_TIME
Definition: commands.h:43
object::last_sp
int32_t last_sp
As last_heal, but for spell points.
Definition: object.h:368
NDI_ALL
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:266
socket_struct::status
enum Sock_Status status
Definition: newserver.h:90
animate_object
void animate_object(object *op, int dir)
Updates the face-variable of an object.
Definition: anim.cpp:44
update_players
void update_players(void)
Send updates to players.
Definition: loop.cpp:674
player::state
uint8_t state
Input state of the player (name, password, etc).
Definition: player.h:131
mapstruct::name
char * name
Name of map as given by its creator.
Definition: map.h:318
object_find_free_spot
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.cpp:3559
mapstruct::in_memory
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:335
EVENT_MAPLEAVE
#define EVENT_MAPLEAVE
A player left a map.
Definition: events.h:47
enter_random_template_map
static void enter_random_template_map(object *pl, object *exit_ob)
The player is trying to enter a randomly generated template map.
Definition: server.cpp:539
object::msg
sstring msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:330
rv_vector
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:370
hit_player
int hit_player(object *op, int dam, object *hitter, uint32_t type, int full_hit)
Object is attacked by something.
Definition: attack.cpp:1907
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:436
free_globals
void free_globals(void)
Cleans all memory allocated for global variables.
Definition: init.cpp:438
map_path_unique
bool map_path_unique(const char *path)
Return true if the given map path leads to a unique map.
Definition: map.cpp:2696
free_server
void free_server(void)
Frees all memory allocated around here:
Definition: init.cpp:1136
ob_apply
method_ret ob_apply(object *op, object *applier, int aflags)
Apply an object by running an event hook or an object method.
Definition: ob_methods.cpp:44
mapstruct::timeout
int32_t timeout
Swapout is set to this.
Definition: map.h:332
MAP_HEIGHT
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:75
MAP_ENTER_Y
#define MAP_ENTER_Y(m)
Default Y coordinate for map enter.
Definition: map.h:82
NDI_DK_ORANGE
#define NDI_DK_ORANGE
DarkOrange2.
Definition: newclient.h:251
find_player_partial_name
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.cpp:114
watchdog
void watchdog(void)
map_newmap_cmd
void map_newmap_cmd(socket_struct *ns)
Sound related function.
Definition: request.cpp:687
get_rangevector
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.cpp:2505
DEAD_OBJECT
@ DEAD_OBJECT
Definition: object.h:161
player::count
uint32_t count
Any numbers typed before a command.
Definition: player.h:122
get_region_by_map
region * get_region_by_map(mapstruct *m)
Gets a region from a map.
Definition: region.cpp:71
save_player
int save_player(object *op, int flag)
Saves a player to disk.
Definition: login.cpp:230
MAP_ENTER_X
#define MAP_ENTER_X(m)
Default X coordinate for map enter.
Definition: map.h:80
process_object
void process_object(object *op)
Main object move function.
Definition: time.cpp:796
object::active_next
object * active_next
Next object in the 'active' list This is used in process_events so that the entire object list does n...
Definition: object.h:287
object_remove
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.cpp:1833
shutdown_state
struct shutdown_s shutdown_state
Definition: c_wiz.cpp:44
cleanup
void cleanup(void)
Clean up everything and exit.
Definition: server.cpp:1257
leave
void leave(player *pl, int draw_exit)
Player logs out, or was disconnected.
Definition: server.cpp:1303
FLAG_UNPAID
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
do_some_living
void do_some_living(object *op)
Regenerate hp/sp/gr, decreases food.
Definition: player.cpp:3293
P_NO_CLERIC
#define P_NO_CLERIC
No clerical spells cast here.
Definition: map.h:238
object::state
uint8_t state
How the object was last drawn (animation)
Definition: object.h:359
mapstruct::unique
uint32_t unique
If set, this is a per player unique map.
Definition: map.h:328
save_map
int save_map(mapstruct *m, int flag)
Saves a map to file.
Definition: map.cpp:1407
archetype::name
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
shutdown_s::next_warn
int next_warn
Definition: commands.h:51
player::socket
socket_struct * socket
Socket information for this player.
Definition: player.h:107
fix_luck
void fix_luck(void)
Fixes luck of players, slowly move it towards 0.
Definition: player.cpp:3927
check_active_maps
void check_active_maps(void)
Finds maps in memory to swap.
Definition: swap.cpp:201
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
commands_clear
void commands_clear()
Clear all registered commands.
Definition: commands.cpp:346
count_players
int count_players(void)
Definition: metaserver.cpp:48
AP_UNAPPLY
#define AP_UNAPPLY
Item is to be remvoed.
Definition: define.h:569
server.h
close_modules
void close_modules()
Clean up all modules which are not disabled.
Definition: init.cpp:80
freearr_x
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
tod.h
player::last_exit
object * last_exit
Last exit used by player or NULL.
Definition: player.h:208
MAP_TIMEOUT
#define MAP_TIMEOUT(m)
Definition: map.h:66
days
static const char * days[]
Ingame days.
Definition: server.cpp:51
TRUE
#define TRUE
Definition: compat.h:11
do_shutdown
static void do_shutdown(void)
Definition: server.cpp:1419
CS_LOGTIME
#define CS_LOGTIME
Definition: config.h:188
cst_lst
CS_Stats cst_lst
Definition: newclient.h:712
mapfile_load
mapstruct * mapfile_load(const char *map, int flags)
Opens the file "filename" and reads information about the map from the given file,...
Definition: map.cpp:1228
object::attacktype
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
rv_vector::direction
int direction
General direction to the targer.
Definition: map.h:374
object::temp_animation
const Animations * temp_animation
A temporary animation.
Definition: object.h:431
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:405
RMParms::region
struct region * region
Definition: random_map.h:96
rv_vector::distance
unsigned int distance
Distance, in squares.
Definition: map.h:371
RMParms::Xsize
int Xsize
Definition: random_map.h:74
FORCE
@ FORCE
Definition: object.h:229
enter_fixed_template_map
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.cpp:448
knowledge_process_incremental
void knowledge_process_incremental(void)
Incrementally send knowledge information to players, and remove information for players who left.
Definition: knowledge.cpp:1439
object.h
player::ticks_played
uint32_t ticks_played
How many ticks this player has played.
Definition: player.h:222
tick_game_time
void tick_game_time()
Definition: time.cpp:184
events_execute_global_event
void events_execute_global_event(int eventcode,...)
Execute a global event.
Definition: events.cpp:30
RMParms::link_source_map
bool link_source_map
Whether to set the reset group (if not already defined) of the source map for this random map.
Definition: random_map.h:104
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:13
SP_WORD_OF_RECALL
#define SP_WORD_OF_RECALL
Definition: spells.h:92
process_players2
static void process_players2(void)
Do all player-related stuff after objects have been updated.
Definition: server.cpp:1048
AUTOSAVE
#define AUTOSAVE
How often (in seconds) the player is saved if he drops things.
Definition: config.h:594
player_update_bg_music
void player_update_bg_music(object *player)
Definition: sounds.cpp:170
unclean_path
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.cpp:350
crypt_string
static char const * crypt_string(char const *str, char const *salt)
Encrypt a string.
Definition: server.cpp:70